2014-11-06 8 views
24

Czy metoda super() nie jest przeznaczona do użycia z metodami statycznymi?interakcja super() i @staticmethod

Kiedy próbuję coś podobnego

class First(object): 
    @staticmethod 
    def getlist(): 
    return ['first'] 

class Second(First): 
    @staticmethod 
    def getlist(): 
    l = super(Second).getlist() 
    l.append('second') 
    return l 

a = Second.getlist() 
print a 

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

Traceback (most recent call last): 
    File "asdf.py", line 13, in <module> 
    a = Second.getlist() 
    File "asdf.py", line 9, in getlist 
    l = super(Second).getlist() 
AttributeError: 'super' object has no attribute 'getlist' 

Gdybym zmienić staticmethods do classmethods i przekazać instancję klasy do super(), wszystko działa dobrze. Czy nie nazywam tutaj nieprawidłowo (typ) lub jest coś, czego mi brakuje?

Odpowiedz

29

Krótka odpowiedź na

jestem wywołanie super (typ) nieprawidłowo tu czy tam coś mi brakuje?

to: tak, nazywasz to niepoprawnie ... I (rzeczywiście, ponieważ) jest coś, czego brakuje.

Ale nie czuj się źle; to niezwykle trudny temat.

W documentation zauważa, że ​​

Jeśli drugi argument zostanie pominięty, super obiekt zwrócony jest niezwiązany.

Etui użycia dla obiektów niezwiązanychsuper jest wyjątkowo wąski i rzadki. Zobacz te artykuły Michele Simionato dla swojej dyskusji na super():

Ponadto twierdzi on silnie do usuwania niezwiązanego super z Python 3 here.

Powiedziałem, że nazwałaś to "niepoprawnie" (chociaż poprawność jest w dużej mierze pozbawiona znaczenia bez kontekstu, a przykład zabawki nie daje dużego kontekstu). Ponieważ niezwiązany super jest tak rzadki i prawdopodobnie po prostu bezzasadny, jak twierdzi Simionato, "poprawnym" sposobem użycia super() jest dostarczenie drugiego argumentu.

W twoim przypadku, to najprostszy sposób, aby Państwa przykładową pracę jest

class First(object): 
    @staticmethod 
    def getlist(): 
    return ['first'] 

class Second(First): 
    @staticmethod 
    def getlist(): 
    l = super(Second, Second).getlist() # note the 2nd argument 
    l.append('second') 
    return l 

a = Second.getlist() 
print a 

Jeśli uważasz, że wygląda zabawny ten sposób, że nie jesteś w błędzie. Ale myślę, że większość ludzi spodziewa się, że zobaczą super(X) (lub mając nadzieję, że kiedy spróbują tego w swoim własnym kodzie), to jest to, co daje Python, jeśli robisz super(X, X).

+1

Czy jest inaczej w Pythonie 3, gdzie 'super()' bez żadnych argumentów jest zwykłym sposobem wywołania tego w zwykłej metodzie? Miałem ten sam problem w Python3, gdy nazywam 'super(). Foo()'. – gerrit

+4

@gerrit: zero-argument Pythona 3 'super()' działa tylko w metodach klasy lub instancji. Wynika to z magii, której używa do określenia klasy, w której jest on zdefiniowany. W statycznych metodach (tak jak w zwykłych funkcjach na poziomie modułu) nadal potrzebujesz dwóch jawnych argumentów. (Forma pojedynczego argumentu również pozostaje niezwiązana w Pythonie 3.) –

1

Po wywołaniu normalnej metody w instancji obiektu, metoda otrzymuje instancję obiektu jako pierwszy parametr. Może uzyskać klasę obiektu hte i jego klasę nadrzędną, więc warto zadzwonić pod numer super.

Po wywołaniu metody classmethod w instancji obiektu lub klasie, metoda otrzymuje klasę jako pierwszy parametr. Może uzyskać klasę nadrzędną, więc warto zadzwonić pod numer super.

Ale kiedy wywołasz metodę staticmethod, metoda nie otrzymuje niczego, nie ma możliwości dowiedzenia się od jakiego obiektu lub klasy została wywołana. To jest powód, dla którego nie można uzyskać dostępu do super w staticmethod.