我正在经历一些 Python 挑战,这个特别的挑战一直困扰着我,并认为值得解释一下。它写道:
让函数 LetterChanges(str) 获取传递的 str 参数并使用以下算法对其进行修改。用字母表中紧随其后的字母替换字符串中的每个字母(即,c 变为 d,z 变为 a)。然后将这个新字符串 (a, e, i, o, u) 中的每个元音大写,最后返回这个修改后的字符串。
例子:
Input: "fun times!"
Output: gvO Ujnft!
Run Code Online (Sandbox Code Playgroud)
编码:
def LetterChanges(str):
letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW"
changes = "bcdEfghIjklmnOpqrstUvwxyzABCDEFGHIJKLMNOPQRSTUVWZ"
mapping = { k:v for (k,v) in zip(str+letters,str+changes) }
return "".join([ mapping[c] for c in str ])
Run Code Online (Sandbox Code Playgroud)
我知道它需要两个字符串、字母和更改。它使用 zip() 函数接受迭代器并“压缩”它们,形成字典形式的迭代器。k:v for (k,v)这是一个字典理解。
我的疑问是:
究竟发生了什么str+letters,str+changes以及为什么必须这样做?
[ mapping[c] for c in str ] 为什么通过这样做,我们完成了用其值替换每个键或在挑战描述中说:“用字母表中紧随其后的字母替换字符串中的每个字母”
这一行:
mapping = { k:v for (k,v) in zip(str+letters,str+changes) }
Run Code Online (Sandbox Code Playgroud)
正如您已经观察到的,使用字典理解语法创建一个字典。生成的字典会将每个字母与翻译字符串时要使用的“新”字母相关联。通常,它会这样做:
mapping = {k: v for k, v in zip(source, destination)}
Run Code Online (Sandbox Code Playgroud)
或者更短:
mapping = dict(zip(source, destination))
Run Code Online (Sandbox Code Playgroud)
但是,下一行执行以下操作:
"".join([ mapping[c] for c in str ])
Run Code Online (Sandbox Code Playgroud)
str在刚刚创建的字典中进行查找时,它会盲目地转换每个字符。如果字符串包含任何不在映射中的字符,则此操作失败。
为了解决这个问题,编写上述代码的人使用了一个愚蠢的技巧,首先将字符串的每个字符添加到映射中,将其与自身相关联,然后为要替换的字符添加相应的映射。
所以在这里:
mapping = { k:v for (k,v) in zip(str+letters,str+changes) }
Run Code Online (Sandbox Code Playgroud)
在str+之前letters和前changes预先将字符串原件和替代两者的全部内容,创造,是不是在字符串中的每个字符映射letters。
这与:
mapping = {k: k for k in str}
mapping.update({k: v for k, v in zip(letters, changes)})
Run Code Online (Sandbox Code Playgroud)
无论如何,这既糟糕又缓慢,所以回答你的问题:
为什么必须这样做?
因为写代码的人决定了。没有必要,它需要O(len(str))时间来构建映射,遍历整个字符串,而实际上没有必要。没有 Python 程序员会这样写。
这样做的“好”方法是:
mapping = dict(zip(source, destination))
return ''.join(mapping.get(c, c) for c in str)
Run Code Online (Sandbox Code Playgroud)
总而言之,上面的代码非常笨拙,恕我直言,以非常混乱的方式完成了任务。
容易发现的问题是:
str.maketrans()和str.translate()内置的方法。X, Y,因此未转换。Zlettersjoin推导完全不需要,不用方括号也可以[]。str覆盖了全局类型 name str,这是不好的,不应该这样做。更好的解决方案是:
def LetterChanges(s):
old = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
new = 'bcdEfghIjklmnOpqrstUvwxyzAZABCDEFGHIJKLMNOPQRSTUVWXY'
table = str.maketrans(old, new)
return s.translate(table)
Run Code Online (Sandbox Code Playgroud)
更好的是只预先计算一次表,然后在连续调用中使用已经创建的表:
def LetterChanges(s, table={}):
if not table:
old = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
new = 'bcdEfghIjklmnOpqrstUvwxyzAZABCDEFGHIJKLMNOPQRSTUVWXY'
table.update(str.maketrans(old, new))
return s.translate(table)
Run Code Online (Sandbox Code Playgroud)
表现:
Hello World!。Hello World!(4.5 倍加速)需要0.400 秒。Hello World!(22.5 倍加速)需要 0.082 秒。| 归档时间: |
|
| 查看次数: |
286 次 |
| 最近记录: |