Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
379 views
in Technique[技术] by (71.8m points)

lambda - Python closure not working as expected

When I run the following script, both lambda's run os.startfile() on the same file -- junk.txt. I would expect each lambda to use the value "f" was set to when the lambda was created. Is there a way to get this to function as I expect?

import os


def main():
    files = [r'C:\_localest.txt', r'C:\_localjunk.txt']
    funcs = []
    for f in files:
        funcs.append(lambda: os.startfile(f))
    print funcs
    funcs[0]()
    funcs[1]()


if __name__ == '__main__':
    main()
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

One way is to do this:

def main():
    files = [r'C:\_localest.txt', r'C:\_localjunk.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]()

Otherwise f is looked up when the function is called, so you get the current (after the loop) value.

Ways I like better:

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))

or even (in python 2.5+):

from functools import partial
for f in files:
    # create a partially applied function
    funcs.append(partial(os.stat, f))

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...