我知道这是一个非常具体的问题,但我希望它也可以对其他人有所帮助。您能否帮助我完全理解Python中的这一行代码:
new_word = ''.join(c if c == g else '_' for c,
g in zip_longest(correct, GUESS, fillvalue='_'))
我即将进行代码审查,这是我唯一不完全理解的代码行。我不熟悉在一行中同时使用“ if”和“ for”。如何用几条语句重写它?
这是zip_longest的Python文档,但我仍然不明白它在上述情况下的工作原理
def zip_longest(*args, fillvalue=None):
# zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-
iterators = [iter(it) for it in args]
num_active = len(iterators)
if not num_active:
return
while True:
values = []
for i, it in enumerate(iterators):
try:
value = next(it)
except StopIteration:
num_active -= 1
if not num_active:
return
iterators[i] = repeat(fillvalue)
value = fillvalue
values.append(value)
yield tuple(values)
答案 0 :(得分:0)
new_word = ''.join(
c if c == g else '_' for c, g in zip_longest(correct, GUESS, fillvalue='_')
)
此代码将名为correct
和GUESS
的2个可迭代对象压缩在一起,以便依次迭代它们的值并根据特定条件连接新的字符串。看起来像是子手式文字游戏中的代码。
出于解释的目的,我们假设correct = hangman
和GUESS = winger
。对于每次迭代,c if c == g else '_'
代码将检查每个单词中相同位置的字符是否相同,如果相同则返回该字符,否则返回一个下划线。在示例单词的第一次迭代中,c
为“ h”,g
为“ w”,因此字符不同,并且返回下划线字符。由于每个示例单词中的第三个字符均为“ n”,因此循环将在第三次迭代中返回“ n”。 fillvalue
中的zip_longest
可确保您完全迭代该对中最长的可迭代对象,并在这种情况下用下划线字符填充较短可迭代对象中的所有缺失值。
因此,在这一点上,我们迭代每个单词中的成对字符并检查它们是否相同将得到['_', '_', 'n', 'g', '_', '_', '_']
。这是因为每个示例单词中的前两个字符不同(返回下划线),第三个和第四个字符相同(返回匹配字符),第五个和第六个字符不同,并且“ hangman”中的最后一个字符之所以将其与fillvalue
中的zip_longest
进行比较,是因为“ winger”比“ hangman”短一个字符。
最后,''.join()
将从理解中返回的元素连接到看起来像"__ng___"
的字符串中。
您可以用稍长的形式完成相同的操作,并从循环中断开连接以更好地了解其工作原理。例如:
from itertools import zip_longest
chars = []
for c, g in zip_longest('hangman', 'winger', fillvalue='_'):
if c == g:
chars.append(c)
else:
chars.append('_')
print(chars)
# ['_', '_', 'n', 'g', '_', '_', '_']
word = ''.join(chars)
print(word)
# __ng___
答案 1 :(得分:0)
在方法调用中这种单行for
语句的用法称为generator expression,如PEP 289中所定义。您可以按如下方式重写此表达式:
new_word = ''
for c, g in zip_longest(correct, GUESS, fillvalue='_'):
if c == g:
new_word += c
else:
new_word += '_'
用简单的术语来说,new_word
的长度与correct
和GUESS
中的较长者相同,并且在除correct
以外的所有位置均由下划线字符组成和GUESS
相同。