2013-06-21 19 views
11

Rozważmy następujący:Puzzling „«krotki»obiekt nie obsługuje przypisanie pozycji” błąd

>>> t = ([],) 
>>> t[0].extend([12, 34]) 
>>> t 
([12, 34],) 
>>> t[0] += [56, 78] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'tuple' object does not support item assignment 
>>> t 
([12, 34, 56, 78],) 
>>> 

Rozumiem, że krotki są niezmienne, ale pozycja w LHS nie jest krotką! (Fakt, że zamierzone przypisanie się udało, mimo to komunikat o błędzie powoduje, że cały scenariusz jest tylko dziwniejszy.)

Dlaczego to zachowanie nie jest uważane za błąd?

+1

Dlaczego ludzie zawsze przychodzą do SO z pytaniem przed przejściem do FAQ Pythona? W dziale FAQ uzyskasz odpowiedź, która została przemyślana, skrupulatnie napisana i sprawdzona przez wielu programistów i przetrwała próbę czasu. Na SO otrzymujesz odpowiedź, że ktoś klika razem w 5 minut, edytuje wielokrotnie przez następne 5 minut, a potem porzuca na resztę czasu. Czy nie wolałbyś tego pierwszego? – abarnert

+0

@abarnert, ponieważ istnieje nieskończona liczba sposobów zadawania pytań, a wyniki google/stackoverflow przechwytują znacznie więcej niż wyszukiwanie w python.org. SO rzuca najszerszą sieć pytań, a gdy się nie powiedzie, zadanie pytania jest zwykle nagradzane szybką odpowiedzią i punktami. W wielu przypadkach powiązane są inne lepsze zasoby, więc ludzie zostaną zwróceni do najlepszego źródła odpowiedzi. – dansalmo

Odpowiedz

8
t[0] += [56, 78] 

jest skrótem

t[0] = t[0].__iadd__([56, 78]) 

gdzie t jest krotką. Część t[0].__iadd__([56, 78]) zmienia listę, ale wynik nie może być zapisany jako t[0].

LHS w języku Python jest zawsze nazwą, nigdy nie jest wartością. W każdym wyrażeniu Pythona, RHS jest obliczane na wartość i przypisywane do nazwy na LHS. W tym przypadku nie można przypisać nazwy t[0], ponieważ t jest krotką.

2

Jest to udokumentowane i wyjaśnione in the Python FAQ.

Aby przeczytać pełną dyskusję, zapoznaj się z wpisami FAQ. Ale krótko, problemem jest to, że ten kod:

t[0] += [56, 78] 

... jest odpowiednikiem tego:

t[0] = t[0].__iadd__([56, 78]) 

__iadd__ skutecznie modyfikuje list w miejscu, a sam wraca; to zadanie podnosi wyjątek.

Jest to not considered a bug, ponieważ jest to nieunikniona konsekwencja działania wszystkich. Chociaż nie jest to oczywiste dla nikogo, kto nie rozumie tych trzech rzeczy, każda próba zmiany rzeczy byłaby bardziej oczywista dla każdego, kto zrozumiałby (i prawdopodobnie złamałby wiele innych, ważniejszych przypadków).

Powiązane problemy