首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从英语翻译到英语

从英语翻译到英语
EN

Code Review用户
提问于 2015-11-25 16:16:23
回答 4查看 1.9K关注 0票数 26

我写了一个python脚本,从一个叫做“魔鬼是部分定时器”的动画把英语转换成Entean语言。我在编码方面很马虎,我知道这个脚本可以做得更好。

在动画中,English的语言叫做Entean,它基本上是英语字母表中的大部分辅音。元音和辅音'L','N','Q‘保持他们原来的位置。ABCDEFGHIJKLMNOPQRSTUVWXYZ改为AZYXEWVTISRLPNOMQKJHUGFDCB。例如,“人”是“土豆泥”,而“世界”则是“狐狸”。

以下是代码:

代码语言:javascript
复制
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".lower()
switched = "AZYXEWVTISRLPNOMQKJHUGFDCB".lower()

usr_txt = input("Enter Englsih text:")

print(usr_txt)

def get_letter(eng_letter):
    if alphabet.find(letter):
        if eng_letter.isupper():
            alpha_place = alphabet.find(letter.lower())
            return(switched[alpha_place].upper())
        else:
            alpha_place = alphabet.find(letter.lower())
            return(switched[alpha_place])
    else:
        return(eng_letter)


ent_word = ""
ent_output = ""


for word in usr_txt.split(" "): 
    ent_word = ""
    for letter in word:
        ent_letter = get_letter(letter)
        ent_word += ent_letter
    ent_output += " " + ent_word


print(ent_output.strip())

如果您感兴趣,可以在https://github.com/Logmytech/English-to-Entean找到更新的代码

EN

回答 4

Code Review用户

回答已采纳

发布于 2015-11-25 17:40:25

最惯用的Python解决方案是使用str.translate()函数,它正好解决了这个问题。

我看不出有什么理由把输入分成几个字,然后把结果重新组合在一起。只需一次转换整个字符串(其中空间映射到自身)。

票数 16
EN

Code Review用户

发布于 2015-11-25 16:35:32

使用字典

我们基本上只是从一个字母映射到另一个字母。最自然的方法是实际使用地图:

代码语言:javascript
复制
to_entean = {...}

建立字典的最简单方法是使用zip()

代码语言:javascript
复制
to_entean = {eng: ent
    for eng, ent in zip(string.ascii_uppercase, 'AZYXEWVTISRLPNOMQKJHUGFDCB')
    }

现在,to_entean['A'] == 'A'to_entean['B'] == 'Z'等等。这简化了您的get_letter函数,使其:

代码语言:javascript
复制
def get_letter(letter):
    ent = to_entean.get(letter.upper(), letter)
    if not letter.isupper():
        ent = ent.lower()
    return ent

字符串压缩

字符串连接速度很慢。而且它读起来很可怕。我们要做的是对get_letter中的每一个字母调用word,然后将它们连接到一起。这就是join()的目的:

代码语言:javascript
复制
ent_word = ''.join(get_letter(letter) for letter in word)

为什么要分裂?

因为get_letter()已经处理了空格,所以我们不必分词。只是改变了整件事

代码语言:javascript
复制
print(''.join(get_letter(letter) for letter in usr_txt))

如果您愿意,也可以拼写如下:

代码语言:javascript
复制
print(''.join(map(get_letter, usr_txt)))

台风

你在这里有个错误:

代码语言:javascript
复制
usr_txt = input("Enter Englsih text:")
                       ^^^^^^^
票数 17
EN

Code Review用户

发布于 2015-11-25 20:39:10

Barry和200_success提出了一些算法建议,我验证了与您的原始版本和我自己的两个修改版本相比以后的速度。但是在处理这些版本之前,让我们回顾一下您的代码:

  • 避免使用顶级代码- In脚本--您先从一些常量开始,然后在顶层请求文本,然后在处理所要求的文本之前定义一个函数get_letter。这里不干净。如果您引入一个函数来翻译整个文本,并且引入一个主函数,则可以将此代码模块化。然后,您将能够从另一个脚本(即下载动画的脚本)导入您的模块,并且您可以从模块调用您的to_entean()。要仍然允许将其作为脚本运行,请在文件末尾使用if __name__ == '__main__': main()。参见下面的代码示例
  • 存储函数的结果,当重复使用时--对于每个字母,您执行三次alphabet.find(),即它太多了两次。做一次,然后就结束了。
  • Bug 1:您将eng_letterletter混合在get_letter() - This中是一个失败,您可能在将代码复制粘贴到代码审查时引入它.他们应该还是一样的
  • Bug 2:标点符号被错误地翻译成- When,使用find在找不到字母时返回-1,这在Python中是一个合法的索引,因此它很高兴地返回该位置的字符:b
  • 请使用完整的变量名-在大多数情况下,像ent_wordeng_letterusr_txt之类的东西应该被拼出来,比如entean_wordenglish_letteruser_text。从长远来看,这样做对每个人来说都更容易。
  • 命名主要是好的--如果您扩展名称,则您的命名大部分是好的。不过,我会将常量设置为UPPER_SNAKE_CASE,以清楚地将它们识别为常量。
  • 将整个字母表作为一个常量--在您的代码中,您需要做大量的lower()upper()操作。特别是设置常量时,这是浪费的。在get_letter()中,这是更容易理解的,但是如果您用小写和大写字母将常量加倍,则不需要调用任何位置。
  • 在紧凑型块中添加垂直间距,- Your get_letter()非常精简,很难读懂,而且所有的return语句混合在一起,很难看出到底发生了什么。我的规则是在ifelifelseforwhile之前添加空行,有时在逻辑代码块前面添加空行。还请注意,函数的前面应该有两个空行。
  • 拆分、添加和剥离字符串有点昂贵--大多数情况下您的代码都是这样做的。知道你的选择,并选择一个最适合你。在重构您的代码时,我保留了一个版本,并与Barry一样加入了一个版本。看看这两个的时差。

代码重构

根据我的评论进行重构时,我将得到以下代码:

代码语言:javascript
复制
FULL_ENGLISH_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
FULL_ENTEAN_ALPHABET = "AZYXEWVTISRLPNOMQKJHUGFDCBazyxewvtisrlpnomqkjhugfdcb"


def get_letter(letter):
    """Return english letter translated to entean."""
    alpha_place = FULL_ENGLISH_ALPHABET.find(letter)

    return FULL_ENTEAN_ALPHABET[alpha_place] if alpha_place >= 0 else letter


def to_entean(text):
    """Return text translated from english to entean."""

    entean_output = ""

    for word in text.split(" "): 
        entean_word = ""

        for letter in word:
            entean_letter = get_letter(letter)
            entean_word += entean_letter

        entean_output += " " + entean_word

    return entean_output.strip()


def main(text=None, with_output=False):

    if with_output:
        print("\nmain")

    if text is None:
        text = input("Enter English text: ")

    if with_output:    
        print(text)
    entean_text = to_entean(text)
    if with_output:
        print(entean_text)

main()的默认参数用于增强下面的测试,因此可以编写得更简单。如果在编写时不考虑其他版本,我很可能也会从常量中去掉FULL_

请注意,当我找到一个字母时,我还将整个get_letter()简化为一个返回,并将字母表扩展到大写字符和小写字符。

使用join的to_entean()的替代版本如下:

代码语言:javascript
复制
def to_entean_join(text):
    """Return text translated from english to entean."""

    return ''.join(get_letter(letter) for letter in text)

性能审查

使用上述main()方法的变体,我测试了您的原始版本、我的版本和200_success版本。我在IPython 2中进行了测试,但我假设即使是Python3也会保持相同的差异。请注意,测试这段代码的性能有点徒劳无益,但是它对于查看代码中的变化如何影响性能也是有用的。

我做的测试是:

代码语言:javascript
复制
In [1]: for test_main in (main_org, main_barry, main, main_v2, main_200_success):
  ...:     print('{:<16}: '.format(test_main.__name__), end='') 
  ...:     %timeit test_main("Hello world! Welcome humans to the Entean world. This text is written in Entean. Cool?")
  ...:

它提供了以下输出:

代码语言:javascript
复制
main_org        : 10000 loops, best of 3: 93.2 µs per loop
main_barry      : 10000 loops, best of 3: 70.7 µs per loop
main            : 10000 loops, best of 3: 57.6 µs per loop
main_v2         : 10000 loops, best of 3: 52.7 µs per loop
main_200_success: The slowest run took 6.24 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 649 ns per loop

可以看出,从性能上看,最明显的赢家是200_success的版本,因为这是一个使用专门翻译方法的专门版本。

另一个有趣的事实是,从分裂、添加和剥离(在main中)到连接(在main_v2中)几乎减少了10%的时间。使用dict(在main_barry中)、upper()isupper()比原始代码快,但比find()慢。在我和巴里的join版本中,我都使用了一个没有map()的版本,如果使用map()的话,时间会改善4-6秒S。

关于测试与各种解决方案初始化成本相关的性能的说明,因为Barry和200_success的版本都有较小的初始化成本(不包括在上面的时间)。但这是在60-70岁S的速度,因此,如果做大量的翻译,它可以合理地使用更多的时间初始化。

从这一切中吸取的主要教训是两方面的:

  • 使用专用资源(如str_translate() )通常可以大大缩短执行时间。
  • 清理代码,避免不必要的操作,也会对执行时间产生重大影响(在这种情况下,执行时间几乎快了50% )。更不用说更容易维护和回到后期阶段了
票数 6
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/111814

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档