2009-07-01 16 views

Odpowiedz

3

Treść klasy jest wykonywana przed zdefiniowaniem klasy, więc domyślne wartości argumentów nie mogą odwoływać się do klasy. Po prostu domyślnym (bez kwalifikacji klasowych) powinno być domyślne ustawienie custom.

11

To jest Foo, który nie jest widoczny, ponieważ jesteś w trakcie jego budowania. Ale skoro jesteś w takim samym zakresie jak custom, można po prostu powiedzieć custom zamiast Foo.custom:

class Foo(object): 
    custom = 1 
    def __init__(self, mycustom=custom): 
     self._custom = mycustom 

jednak pamiętać, że zmiana Foo.custom później nie będzie miało wpływu na wartość custom które następnie utworzonego Foo Zobaczmy :

class Foo(object): 
    custom = 1 
    def __init__(self, mycustom=custom): 
     self._custom = mycustom 

one = Foo() 
Foo.custom = 2 
two = Foo() 
print (two._custom) # Prints 1 

Wykorzystując wartości domyślnej Sentinel zamiast można dostać to, co chcesz:

class Foo(object): 
    custom = 1 
    def __init__(self, mycustom=None): 
     if mycustom is None: 
      self._custom = Foo.custom 
     else: 
      self._custom = mycustom 

one = Foo() 
Foo.custom = 2 
two = Foo() 
print (two._custom) # Prints 2 
+0

Przyjemnie, z wyjątkiem porównań z Brak należy zawsze robić za pomocą 'jest'. –

+0

"Chociaż oznacza to, że zmiana Foo.custom w późniejszym czasie nie wpłynie na wartość niestandardową, która została później utworzona przez Foos": Warto zauważyć, że zawsze jest tak w przypadku funkcji, dla których wartości domyślne są tworzone i powiązane tylko raz, kiedy funkcja jest tworzona, więc nawet * jeśli * możliwe było odniesienie Foo.custom do wartości domyślnej, nadal byłoby tak, że domyślna wartość nie zmieniłaby się, gdyby zmieniono Foo.custom. – Miles

+0

Dlaczego dopuszczalne jest odwoływanie się do Foo.custom do treści __init__, ale nie do listy inicjalizatora? W obu przypadkach "jesteśmy w trakcie budowania". –

2

pojawia się następujący błąd:

Traceback (most recent call last): 
    Line 1, in <module> 
    class Foo(object): 
    Line 3, in Foo 
    def __init__(self, custom=Foo.custom): 
NameError: name 'Foo' is not defined 

To dlatego, że nazwa Foo jest w trakcie zdefiniowana jako funkcja __init__ jest określona i nie jest w pełni dostępny w tym czasie.

Rozwiązaniem jest unikać używania nazwy Foo w definicji funkcji (ja też przemianowany custom paramter do acustom aby odróżnić ją od Foo.custom):

class Foo(object): 
    custom = 1 
    def __init__(self, acustom=custom): 
     self._custom = acustom 
x = Foo() 
print x._custom 
+0

Ale wiesz, że możesz odnosić się do Foo.custom w _body_ of __init__, nie tylko na liście inicjalizatora. To wydaje mi się niespójne. –

+0

"Zmieniłem również nazwę niestandardowego parametru, aby odróżnić go od Foo.custom": To jest prawdopodobnie dobry pomysł, ale nie jest to absolutnie konieczne, aw niektórych sytuacjach w Pythonie jest nawet idiomem, aby były takie same (najczęściej z zagnieżdżonymi funkcjami wewnątrz pętli, np. lambda x = x: ...) – Miles

6

Co robimy zamiast jest następujący

class Foo(object): 
    custom = 1 
    def __init__(self, arg=None) 
     self._custom = self.custom if arg is None else arg 

Pomija to mylące zagadnienie, czy nazwa Foo została jeszcze zdefiniowana.

+0

Dlaczego powinien być mylący? Przed utworzeniem instancji klasa powinna zostać zainicjowana. __init__ jest uruchamiany, gdy instancja jest tworzona, więc zmienne klasy powinny być widoczne. –

+0

@rdm: Zobacz komentarz Milesa do mojej odpowiedzi. Parametry domyślne są określane podczas tworzenia funkcji (np. Podczas tworzenia klasy w tym przypadku), a nie podczas jej wywoływania. – RichieHindle

Powiązane problemy