2016-07-01 2 views
1

Я использую понимание списка, чтобы присвоить значение атрибуту класса в Python2.7. Я заметил, что это добавляет переменную, используемую в понимании списка как атрибут класса.Python 2.7 list comprehension leaks variable name

class MyClass: 
    some_strings = [s for s in ('Foo','Bar')] 

print MyClass.s 

Output: 'Bar' #?? 

Может кто-нибудь объяснить, почему это происходит? Есть ли что-то неправильное в использовании списка?

ответ

2

Нет ничего плохого. Использование понимания списка добавляет свою переменную в локальную область, как и цикл for. При использовании внутри определения класса указанная локальная область используется для инициализации атрибутов класса. У вас должно быть del имя s, если вы не хотите этого в своем классе.

class MyClass: 
    some_strings = [s for s in ('Foo','Bar')] 
    del s 

Обратите внимание, что в Python 3 (проверено с 3.4), список понимание будет не добавить свою переменную в локальной области видимости.

+1

Я этого не знал. Я переводил код Python3 в Python2, и у меня была странная ошибка, из-за которой атрибут был переопределен переменной в понимании списка. Поведение Python3 определенно является разумным улучшением! Я удивлен, что никогда не видел этого в общих ошибках Python2 ... –

+0

@JacquesGaudin Я был действительно удивлен, когда столкнулся с противоположным эффектом - что-то не переписывалось, когда я этого ожидал. Было немного хаки ... Я согласен с тем, что поведение в Py3 кажется более чистым и, как правило, поощряет лучший код. – MisterMiyagi

1

Explaination из Guido Van Rossum

Мы также сделали еще одно изменение в Python 3, чтобы улучшить эквивалентность между списковых и выражениями генератора. В Python 2 понимание списка «просачивает» переменную управления контуром в окружающую область: x = 'before' a = [x for x in 1, 2, 3] print x # this prints '3', not 'before'

Это был артефакт первоначальной реализации списков; это был один из «грязных маленьких секретов» Питона в течение многих лет. Это началось как преднамеренный компромисс, чтобы сделать переписные слова ослепительно быстрыми, и, хотя это не было обычной ловушкой для начинающих, это определенно ужалило людей изредка. Для выражений генератора мы не могли этого сделать. Выражения генератора реализуются с использованием генераторов, выполнение которых требует отдельного кадра выполнения. Таким образом, выражения генератора (особенно, если они повторяются в короткой последовательности) были менее эффективными, чем понимание списков.

Однако в Python 3 мы решили исправить «грязный маленький секрет» из понятий списка, используя ту же стратегию реализации, что и для выражений генератора. Таким образом, в Python 3 приведенный выше пример (после модификации использования print (x) :-) будет печатать «before», доказывая, что «x» в понимании списка временно затеняет, но не переопределяет «x» в окружающем объем.