2011-04-08 2 views
1

일부 lambdas를 지나가는 것에 의존하는 Python 코드가 몇 개 있습니다. 몇 개의 다른 장소에 복사되지만, 목록에서 튀어 나오면 다른 모든 목록에서 마술처럼 사라집니다. 이것이 버그인지 아닌지는 알 수 없습니다. 나는 이것을 CPython에서 돌리고 있음을 주목할 것이다.람다가 사라지는 이유는 무엇입니까?

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) 

파이썬은 참조 카운팅을 수행 한 경우, 새 목록이 참조 카운트를 증가해야하지만, 람다는 사라지고 유지 :

다음은 나의 점을 설명하기 위해 몇 가지 코드입니다.

는 심지어 있도록이 시도 람다의 새로운 인스턴스가 생성되는 첫 번째 루프를 통해 각 시간 : 아직도

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) 

없이 이동합니다.

누구에게 무슨 일이 일어나는가에 대한 단서가 있습니까?

답변

4

list.pop은 목록을 제자리에서 수정합니다. 목록에 대한 참조가있는 모든 사람이 동일한 변경 사항을 봅니다. 두 번째 복사본을 저장하지 않고 하나의 단일 목록에 여러 참조를 저장하면 첫 번째 while 루프에서 비 웁니다.

당신은 (모두를 포함하여, 처음부터 끝까지 조각 인) a[:]을 통해 목록을 복사 할 수 있습니다 - 그것은 shallow copy의 참고 -과 (자신의 클래스 '인스턴스 포함) 거의 모든 것을 copy 모듈.

+2

'c'에'b'의 복사본을 추가하려면'c.append (b [:]) '라고 말할 수 있습니다. – dfan

+0

감사. '복사'모듈을 사용하여 여기 내 문제를 해결. – supercheetah

2

귀하의 예제 설치 방법은 lambdas에 대한 참조가있는 유일한 방법은 listB입니다. CB이 아니고B 인 람다에 대한 참조를 보유합니다. B에서 람다를 꺼내면 람다에 대한 참조가 남아 있지 않습니다. 현재 남은 것은 C이며 B에 대한 참조는 비어 있습니다.


은 또한, 좋은 팁이 다른 답변의 의견에서 지적되었다

제공 : Dfan

당신이 나에 C의 사본을 추가하려는 경우, 당신은 할 수 c.append ([:] B 형)라고

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

Y ou는 참조 (얕은 복사본) 만 만들고, "딥 복사본"을 사용해야하는 것과 같은 값을 실제로 복사합니다.

관련 문제