python - 使用循环中的变量在循环中生成函数会导致变量的阴影效应
问题描述
我想在循环中生成从循环访问变量的小函数。然后我想一次编写和应用所有功能。MWE 看起来是这样的:
from functools import reduce
def compose(*funcs):
return lambda x: reduce(lambda y, f: f(y), reversed(funcs), x)
def replace_values_by_type(text, values, types) -> str:
def peek(x):
print('peek:', x)
return x
replacements = [lambda txt: peek(peek(txt).replace(peek(val), f'<{peek(typ)}>')) for val, typ in zip(values, types)]
replace = compose(*replacements)
text_with_replacements = replace(text)
print(values)
print(types)
print(text)
print(text_with_replacements)
print()
return text_with_replacements
replace_values_by_type('this is a test sentence', ['is', 'test'], ['A', 'B'])
当我运行它时,我希望得到“this <A> a <B> sentence”。但实际上只使用了最后一对val
and from 循环。typ
所以我猜会发生一些阴影或覆盖。你能解释一下吗?
-> % py mwe.py
peek: this is a test sentence
peek: test
peek: B
peek: this is a <B> sentence
peek: this is a <B> sentence
peek: test
peek: B
peek: this is a <B> sentence
['is', 'test']
['A', 'B']
this is a test sentence
this is a <B> sentence
顺便提一句。为了隔离问题,我还编写了这样的函数:
def replace_values_by_type(text, values, types) -> str:
replacements = []
for val, typ in zip(values, types):
def f(txt):
return txt.replace(val, f'<{typ}>')
replacements.append(f)
text_with_replacements = text
for f in replacements:
text_with_replacements = f(text_with_replacements)
return text_with_replacements
print(replace_values_by_type('this is a test sentence', ['is', 'test'], ['A', 'B']))
问题仍然相同。
解决方案
列表推导式创建的所有闭包都在同一个变量范围内,并且循环只有一个val
and变量实例。typ
稍后调用闭包时,变量具有上次迭代的值。
您需要在每次迭代的唯一范围内生成闭包。一种方法是编写一个单独的函数来返回闭包,因为每个函数都建立了一个新的范围。
def replacer(val, typ):
return lambda txt: peek(peek(txt).replace(peek(val), f'<{peek(typ)}>'))
replacements = [replacer(val, typ) for val, typ in zip(values, types)]
推荐阅读
- python-3.x - Python Tabula 库 - 输出文件为空
- json - 如何处理JSON数据swiftUI中的`self`变量
- java - 如何在 ActionListener 中覆盖 JLabel 上的图像?
- java - 我在构建 android 应用程序时遇到运行时错误
- linux - 装配输出很奇怪
- r - 随机分配以等比例条件 R
- python - 在 Anaconda Python (Windows) 中安装 Matlab 引擎
- ios - 通过按钮更改颤振音量级别
- c# - 使用 Azure AD 重定向
- javascript - 如何在 Electron 渲染器进程中使用 RxJs 等模块?