开发者

Why are my lambdas disappearing?

I have some Python code that's dependent upon passing around some lambdas, and they get copied to a few different places, but I'm finding that when I pop them out of a list, they just magically disappear from all the other lists. I don't know if this is a bug or not. I'll note that I'm running this on CPython.

Here's some code to illustrate my point:

a = lambda x: x+x*3
b = []
c = []

for i in range(3):
    b.append(a)

for i in range(3):
    c.append(b)

while b:
    print b.pop()(5)

for d in c:
    while d:
        print d.pop()(10)

If Python were doing reference counting, the new lists should increment the refcount, but the lambdas just keep 开发者_JS百科disappearing.

I even tried this so that each time through the first loop a new instance of the lambda is created:

b = []
c = []

for i in range(3):
    b.append(lambda x: x+x*3)

for i in range(3):
    c.append(b)

while b:
    print b.pop()(5)

for d in c:
    while d:
        print d.pop()(10)

Still no go.

Anyone have a clue on what's happening here?


list.pop modifies the list in-place. So everyone with a reference to the list sees the same change. You're not storing copies in the second, you're just storing several references to one single list, which is then emptied in the first while loop.

You can copy lists through a[:] (which is a slice from the beginning to the end, including both) - note that it's a shallow copy - and nearly everything (including your own classes' instances) with the copy module.


The way you have your example setup, the only thing holding a reference to your lambdas is the list B. C holds a reference to list B not to the lambdas inside of B. When you pop the lambdas out of B, no references to the lambda remain. What you are left with is C with the references to B which is now empty.


Also, a good tip was pointed out in the comments of another answer:

Credit: Dfan

If you want to append a copy of b to c, you could say c.append(b[:])


import copy
for i in range(3):
    b.append(copy.deepcopy(a))
for i in range(3):
    c.append(copy.deepcopy(b))

You are only creating references (shallow copy), to truly copy the values like what you expect you must use a "deep copy".

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜