2010-05-21 13 views
8

kodu w test.py:Klasy bazowe Pythona udostępniają atrybuty?

class Base(object): 
    def __init__(self, l=[]): 
     self.l = l 

    def add(self, num): 
     self.l.append(num) 

    def remove(self, num): 
     self.l.remove(num) 

class Derived(Base): 
    def __init__(self, l=[]): 
     super(Derived, self).__init__(l) 

Pythona sesji powłoki:

Python 2.6.5 (r265:79063, Apr 1 2010, 05:22:20) 
[GCC 4.4.3 20100316 (prerelease)] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import test 
>>> a = test.Derived() 
>>> b = test.Derived() 
>>> a.l 
[] 
>>> b.l 
[] 
>>> a.add(1) 
>>> a.l 
[1] 
>>> b.l 
[1] 
>>> c = test.Derived() 
>>> c.l 
[1] 

Spodziewałem "C++ - jak" zachowanie, w którym każdy obiekt pochodzi zawiera własne wystąpienie klasy bazowej. Czy tak jest nadal? Dlaczego każdy obiekt wydaje się współdzielić tę samą instancję listy?

+0

możliwe duplikat [ "najmniejsze zdziwienie" w Pythonie: The Zmienna domyślne argumentów] (http://stackoverflow.com/questions/1132941/least-astonishment-in-python- the-mutable-default-argument) –

Odpowiedz

14

Powodujesz błąd wspólnego nowobok Pythona.

Zobacz moją odpowiedź tutaj: How should I declare default values for instance variables in Python?

Pokrótce wyjaśnił, Python interpretuje definicje klas tylko raz. Oznacza to, że wszystko zadeklarowane w metodzie __init__() jest tworzone tylko raz. Lub, innymi słowy, domyślny argument listy na liście [] jest tworzony tylko raz.

Wtedy przypisuje odniesienie do tej samej instancji za każdym razem, gdy tworzysz nową klasę, stąd zachowanie, którego się nie spodziewałeś.

pythonowy sposobem jest ten (kod częściowe):

def __init__(self, arg=None): 
    if arg is None: 
     arg = [] 
    self.arg = arg 

Ponadto, należy rozważyć użycie lepsze niż l konwencję nazewnictwa, co jest trudne do odczytania i może być mylone jako 1 lub |.

+0

+1 dla poprawnej odpowiedzi, ale byłoby miło przeliterować to tutaj, przynajmniej na krótko. – Etaoin

+1

Ja to zrobię. ':]' –

+0

Oczywiście, jest to fragment testu. Nigdy nie wybrałbym "l" jako nazwy zmiennej. – tad

2

To się nazywa zmienny błąd domyślnego argumentu, który jest zwykle tworzony przez osoby niezwiązane z Pythonem. Gdy podasz zmienną jako domyślny argument, ten sam obiekt zostanie użyty w instancjach, gdy wymagany będzie domyślny argument. Get lepiej zrozumieć sprawdzić ważne ostrzeżenie sekcję http://docs.python.org/tutorial/controlflow.html#default-argument-values

W kodzie, instancja używanego na zmienny domyślne argumenty (a pusta lista obiektów) w To wezwanie startowych i podczas tworzenia instancji B, który z kolei o nazwie metoda init Base, ponownie użył tego samego obiektu, który użył w swoim init. Na prostszych słowach a.l i b.l wskazują ten sam obiekt listy.

bardzo podobna do dyskusji - "Least Astonishment" and the Mutable Default Argument

+0

To nie jest błąd, to sposób działania tego języka. –

Powiązane problemy