如何在没有函数调用的情况下创建Python嵌套生成器管道?

icnyk63a  于 2023-03-31  发布在  Python
关注(0)|答案(1)|浏览(77)

我有以下代码片段。

x = (w for w in words if len(w) == 5)

def mk_gen(x, idx, val):
    return (w for w in x if w[idx] == val)

pattern = 'he_l_'
for idx, val in enumerate(pattern):
    if val == '_':
        continue
    x = mk_gen(x, idx, val) # Method 1
    # x = (w for w in x if w[idx] == val) # Method 2

print((list(x)))
# Method 1 -> ['heald', 'heals', 'heels', 'heild', 'heily', 'heils', 'helly', 'hello', 'hells', 'herls']
# Method 2 -> []

这里的单词是英语词典中的单词列表。
方法1给出了预期的输出。
然而,方法2并不这样做,尽管事实上方法1正在做与方法2相同的事情,但调用一个返回它的函数,而不是直接分配新的生成器。
为什么会发生这种情况?
我尝试了另一种方法来创建一个新的生成器,使用函数调用。

def mk_gen_1(x, idx, val):
    for w in x:
        if w[idx] == val:
            yield w

这一个也工作,但原来的方法2不.
我在Pythonic way to chain python generator function to form a pipeline中找到的另一个不起作用。

gen_2_steps = [(lambda g:(w for w in g if w[idx] == val)) for idx, val in enumerate(pattern) if val != '_']
x = reduce(lambda g, f: f(g), [x, *gen_2_steps]) # Method 3
print(list(x))

这一个工作,但它不是我打算做的。我打算通过使用for循环创建生成器,而不调用另一个函数。

# Works
f2_1 = lambda g:(w for w in g if w[0] == 'h')
x = f2_1(x)
f2_2 = lambda g:(w for w in g if w[1] == 'e')
x = f2_2(x)
f2_3 = lambda g:(w for w in g if w[3] == 'l')
x = f2_3(x)
print(len(list(x)))
pieyvz9o

pieyvz9o1#

方法1和方法2使用两组不同的变量。
方法1使用由mk_gen定义的本地名称idxval;它基本上定义了一个闭包,其中传递给mk_gen的值即使在mk_gen返回之后也会被生成器记住。
方法2使用由for循环定义(和重新定义)的名称idxval,因为生成器表达式与这些变量处于同一作用域。

相关问题