Python的itertools模块中使用zip_longest的代码行

时间:2019-04-30 13:06:05

标签: python python-3.x itertools

我知道这是一个非常具体的问题,但我希望它也可以对其他人有所帮助。您能否帮助我完全理解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)

2 个答案:

答案 0 :(得分:0)

new_word = ''.join(
    c if c == g else '_' for c, g in zip_longest(correct, GUESS, fillvalue='_')
    )

此代码将名为correctGUESS的2个可迭代对象压缩在一起,以便依次迭代它们的值并根据特定条件连接新的字符串。看起来像是子手式文字游戏中的代码。

出于解释的目的,我们假设correct = hangmanGUESS = 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的长度与correctGUESS中的较长者相同,并且在除correct以外的所有位置均由下划线字符组成和GUESS相同。