问题
What is the Python mechanism that makes it so that
[lambda: x for x in range(5)][2]()
is 4?
What is the usual trick for binding a copy of x to each lamba expression so that the above expression will equal 2?
My final solution:
for template, model in zip(model_templates, model_classes):
def create_known_parameters(known_parms):
return lambda self: [getattr(self, p.name)
for p in known_parms]
model.known_parameters = create_known_parameters(template.known_parms)
回答1:
I usually use functools.partial:
[ partial(lambda x: x, x) for x in range(5) ]
Or, of course, you can do it yourself:
[ (lambda x: (lambda: x))(x) for x in range(5) ]
回答2:
>>> [lambda x=x: x for x in range(5)][2]()
2
回答3:
Since no one's answered the "what is the mechanism" part, and this surprised me when I first read it, here's a go:
This:
ls = [lambda: x for x in range(5)]
Is a bit like this:
ls = []
x = 0
ls.append(lambda: x)
x = 1
ls.append(lambda: x)
x = 2
ls.append(lambda: x)
x = 3
ls.append(lambda: x)
x = 4
ls.append(lambda: x)
Each of those lambdas has its own scope, but none of those scopes contain an x. So they're all going to be reading the value of x by looking in an outer scope, so of course they must all be referring to the same object. By the time any of them are called, the loop is done and that object is the integer 4.
So even though these lambdas look like functions involving only immutable values, they can still be affected by side effects, because they depend on the bindings in an outer scope, and that scope can change.
You could of course further change what these lambdas return by rebinding x, or make them throw an error by unbinding it. In the list comprehension version though, the x is only bound in a private scope inside the list comprehension, so you can't mess with it (as easily).
The solution is of course to arrange things so that each lambda has an x in its local scope (or at least some outer scope that is not shared between the lambdas), so that they can all refer to different objects. Ways to do that have been shown in the other answers.
来源:https://stackoverflow.com/questions/9189702/python-closures-and-cells-closed-over-values