2011-01-01 18 views
17

rzucić okiem na poniższy kawałek kodu, który pokazuje listę zrozumieniem ..Python lista rozumienie nadrzędnych wartości

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

Po uruchomieniu przykład kodu w Python 2.6 drukuje , ale po uruchomieniu go w trybie Python 3.x drukuje on .

Co było powodem zmiany zachowań i dlaczego jest wyjście w Python 3.x?

Z góry dziękuję!

+2

Wow. Mam szczęście, że znalazłem to tutaj, szukałem błędu przez wiele tygodni, gdybym natknął się na to we własnym kodzie. +1 dla pytania, -1 dla Pythona :( – Kos

+0

Podobne pytanie tutaj: http://stackoverflow.com/questions/4198906/python-list-comprehension-rebind-names-even-after-skope-of-comprehension-is- to –

Odpowiedz

30

Dawne zachowanie było błędem, ale nie można go było łatwo naprawić, ponieważ opierał się na nim jakiś kod.

Zmienna i na liście powinna być inna niż i od tej na najwyższym poziomie. Logicznie rzecz biorąc, powinien on mieć swój własny zakres, który nie wykracza poza pojmowanie, ponieważ jego wartość ma sens jedynie w rozumieniu. Ale w Pythonie 2.x ze względu na szczegóły implementacji zakres był większy niż to konieczne, powodując, że zmienna "wyciekła" do zewnętrznego zakresu, powodując dezorientujące wyniki.

Python 3.0 celowo nie miał być kompatybilny wstecz z poprzednimi wersjami, więc wykorzystali okazję, aby naprawić to niepożądane zachowanie.

W wydaniach Python 2.3 i nowszych, zrozumienie listy "przecieka" zmienne kontrolne każdego z nich do zakresu zawierającego. Jednak takie zachowanie jest przestarzała, a opierając się na nim nie zadziała w Pythonie 3,0

Source

7

Tak, nie ma powodu, a powodem jest to, że nie chcą tymczasowej zmiennej w wymień listę, aby wyciekł do zewnętrznej przestrzeni nazw. Jest to więc celowa zmiana, która wynika ze sposobu rozumienia listy, który jest teraz cukrem syntaktycznym służącym do przekazania wyrażenia generatora do listy().

Dotyczy: PEP3100.

0

Wygląda dla mnie jako zmiana zakresu.

Potwierdziłem twój wynik w Pythonie 2.6; rzeczywiście drukuje 99, która jest ostatnią wartością przypisaną do i w zrozumieniu listy.

4

Mark Byers odpowiedział na to doskonale.

tak na marginesie ..
w Pythonie 2.x, jeśli zmienisz swoje wsporniki do parens (tworzących wyrażenie generator zamiast listy zrozumieniem), można zauważyć, że zmienna sterowania jest nie wyciekły .

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

vs.

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

(oczywiście w Pythonie 3, to jest stałe i listowych nie przeciekać zmiennych kontrolnych)

+0

To dobra uwaga, ale należy również zauważyć, że 's' również nie zawiera teraz listy, więc aby uzyskać pożądany wynik końcowy, musisz wykonać' list (s) '. – Keith