当我运行以下脚本时,两个lambda都在同一个文件--junk.txt上运行os.startfile().我希望每个lambda使用值"f"设置为lambda创建时.有没有办法让它按照我的预期运作?
import os
def main():
files = [r'C:\_local\test.txt', r'C:\_local\junk.txt']
funcs = []
for f in files:
funcs.append(lambda: os.startfile(f))
print funcs
funcs[0]()
funcs[1]()
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
Joc*_*zel 22
一种方法是这样做:
def main():
files = [r'C:\_local\test.txt', r'C:\_local\junk.txt']
funcs = []
for f in files:
# create a new lambda and store the current `f` as default to `path`
funcs.append(lambda path=f: os.stat(path))
print funcs
# calling the lambda without a parameter uses the default value
funcs[0]()
funcs[1]()
Run Code Online (Sandbox Code Playgroud)
否则f在调用函数时会查找,因此您将获得当前(循环后)值.
我更喜欢的方式:
def make_statfunc(f):
return lambda: os.stat(f)
for f in files:
# pass the current f to another function
funcs.append(make_statfunc(f))
Run Code Online (Sandbox Code Playgroud)
甚至(在python 2.5+中):
from functools import partial
for f in files:
# create a partially applied function
funcs.append(partial(os.stat, f))
Run Code Online (Sandbox Code Playgroud)
重要的是要理解,当变量成为闭包的一部分时,它是变量本身,而不是被包含的值。
这意味着循环中创建的所有闭包都使用相同的变量f,该变量在循环结束时将包含循环内使用的最后一个值。
然而,由于语言的定义方式,这些捕获的变量在 Python 2.x 中是“只读”的:任何赋值都会使变量成为本地变量,除非声明它global(Python 3.x 添加了nonlocal关键字以允许写入外部作用域的本地变量) )。
正如 Jochen Ritzel 在他的回答中所说,避免这种变量捕获并获取值捕获的常见习惯用法是编写
lambda f=f: os.startfile(f)
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为默认参数值是在函数创建时评估的,并且f不是外部变量,而是一个函数参数,它将具有您想要的默认值(因此这个 lambda 只是一个具有参数默认值的函数,不会关闭任何词法不再有变量)。