Почему исчезают мои лямбды? - PullRequest
1 голос
/ 08 апреля 2011

У меня есть некоторый код 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)

Если бы Python выполнял подсчет ссылок, новые списки должны увеличивать счет, но лямбды просто продолжают исчезать.

Я даже пытался это сделать так, чтобы каждый раз в первом цикле создавался новый экземпляр лямбды:

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)

Все еще не уходи.

Кто-нибудь знает, что здесь происходит?

Ответы [ 3 ]

4 голосов
/ 08 апреля 2011

list.pop изменяет список на месте. Так что каждый, кто ссылается на список, видит одно и то же изменение. Вы не сохраняете копии во втором, вы просто храните несколько ссылок на один единственный список, который затем очищается в первом цикле while.

Вы можете копировать списки через a[:] (это фрагмент от начала до конца, включая оба) - обратите внимание, что это мелкая копия - и почти все ( включая экземпляры ваших собственных классов) с помощью модуля copy.

2 голосов
/ 08 апреля 2011

При настройке вашего примера, единственное, что содержит ссылку на ваш lambdas, это list B.C содержит ссылку на list B , а не на лямбды внутри B.Когда вы извлекаете лямбды из B, ссылки на лямбду не остаются.То, что у вас осталось, это C со ссылками на B, который сейчас пуст.


Кроме того, в комментариях к другому ответу был указан хороший совет:

Кредит: Dfan

Если вы хотите добавить копию b к c, вы можете сказать c.append (b [:])

1 голос
/ 08 апреля 2011
import copy
for i in range(3):
    b.append(copy.deepcopy(a))
for i in range(3):
    c.append(copy.deepcopy(b))

Вы только создаете ссылки (поверхностное копирование), чтобы действительно копировать значения, как вы ожидаете, вы должны использовать «глубокое копирование».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...