Переопределение значения понимания списка Python - PullRequest
17 голосов
/ 01 января 2011

посмотрите на следующий фрагмент кода, который показывает понимание списка ..

>>> i = 6
>>> s = [i * i for i in range(100)]
>>> print(i)

Когда вы выполняете пример кода в Python 2.6 , он печатает 99, но когда вы запускаете его в Python 3.x , он печатает 6 .

В чем причина изменения поведения и почему вывод 6 в Python 3.x ?

Заранее спасибо!

Ответы [ 4 ]

31 голосов
/ 01 января 2011

Старое поведение было ошибкой, но его нельзя было легко исправить, так как на него полагался какой-то код.

Переменная i в понимании списка должна отличаться от i от той, что вверхний уровень.По логике он должен иметь свою собственную область, которая не выходит за пределы понимания, поскольку его значение имеет смысл только внутри понимания.Но в Python 2.x из-за деталей реализации область действия была больше, чем необходимо, что приводило к тому, что переменная «просачивалась» во внешнюю область, вызывая запутанные результаты, которые вы видите.

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

В Python 2.3 и более поздних выпусках понимание списка «пропускает» управляющие переменные каждого из них, содержащиеся в нем, в содержащийобъем.Тем не менее, это поведение устарело, и полагаться на него не будет работать в Python 3.0

Source

7 голосов
/ 01 января 2011

Да, есть причина, и причина в том, что они не хотели, чтобы временная переменная в понимании списка просачивалась во внешнее пространство имен. Таким образом, это преднамеренное изменение, которое является результатом того, что понимание списка теперь является синтаксическим сахаром для передачи выражения генератора в list ().

Ссылка: PEP3100 .

4 голосов
/ 02 января 2011

Марк Байерс ответил на него отлично.

просто как примечание.
в Python 2.x, если вы измените скобки на скобки (создавая выражение генератора вместо понимания списка),вы заметите, что управляющая переменная не просочилась.

>>> i = 6
>>> s = (i for i in range(100))
>>> print i
6

против

>>> i = 6
>>> s = [i for i in range(100)]
>>> print i
99

(конечно, в Python 3 это исправлено, и списокПонимания больше не влияют на переменные контроля утечки)

0 голосов
/ 01 января 2011

Выглядит как изменение в области видимости для меня.

Я подтвердил ваш результат в Python 2.6;он действительно печатает 99, что является последним значением, присвоенным i в понимании списка.

...