I have seen this question , but i still cannot get why such simple example does not work:
mylist = ["alice", "bob", "greta"]
funcdict = dict(((y, lambda x: x==str(y)) for y in mylist))
funcdict['alice']("greta")
#True
funcdict['alice']("alice")
#False
funcdict['greta']("greta")
#True
How is it different from:
[(y, y) for y in mylist]
Why y
is not evalueated within each step of iteration?
The y
in the body of the lambda
expression is just a name, unrelated to the y
you use to iterate over mylist
. As a free variable, a value of y
is not found until you actually call the function, at which time it uses whatever value for y
is in the calling scope.
To actually force y
to have a value at definition time, you need to make it local to the body via an argument:
dict((y, lambda x, y=z: x == str(y)) for z in mylist)
((y, lambda x: x==str(y)) for y in mylist)
y
inside the lambda is not bound at the time of the genration expression defined, but it's bound when it's called; When it's called, iteration is already done, so y
references the last item greta
.
One way to work around this is to use keyword argument, which is evaluated when the function/lambda is defined:
funcdict = dict((y, lambda x, y=y: x == y) for y in mylist)
funcdict = {y: lambda x, y=y: x == y for y in mylist} # dict-comprehension
or you can use partial
:
funcdict = {y: partial(operator.eq, y) for y in mylist}
y
is evaluated while the mylist
is iterated.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.