classmethod
i staticmethod
są opisowe, a żadna z nich nie robią tego, co można się spodziewać, nie tylko staticmethod
.
Po uzyskaniu dostępu A.one
, to stworzenie metody związanej na A
, to co, że atrybutem B
, ale ponieważ to wiąże się z A
The cls
argumentem zawsze będzie A
, nawet jeśli nazywają B.one
(jest to przypadek zarówno w Pythonie 2, jak i Pythonie 3. wszędzie jest źle.
Po uzyskaniu dostępu A.two
, to powrót surowego obiektu funkcyjnego (deskryptor staticmethod
nie trzeba robić nic specjalnego oprócz zapobiegania wiązania, które przechodzą self
lub cls
, więc po prostu wraca co owinięty). Ale ten surowy obiekt funkcji jest następnie dołączany do B
jako niezwiązana metoda instancji, ponieważ bez zawijania staticmethod
jest tak, jak zdefiniowałeś to normalnie.
Powodem, dla którego ten ostatni działa w Pythonie 3, jest to, że Python 3 nie ma pojęcia metod niezwiązanych. Posiada funkcje (do których dostęp uzyskuje się poprzez instancję klasy związanej) i powiązane metody, gdzie Python 2 ma funkcje, niezwiązane metody i związane metody.
Metody niezwiązane sprawdzają, czy są wywoływane z obiektem o poprawnym typie, a tym samym o błędzie. Proste funkcje wymagają tylko poprawnej liczby argumentów.
Dekorator staticmethod
w Pythonie 3 wciąż zwraca surowy obiekt funkcji, ale w Pythonie 3 jest to w porządku; ponieważ nie jest to specjalny niezwiązany obiekt metody, jeśli wywołasz go na samej klasie, to jest to tak jak funkcja z wyświetlaniem nazw, a nie jakakolwiek metoda.chcesz zobaczyć problem, jeśli starali się zrobić:
B().two()
chociaż, bo to uczyni metodę związaną z tym wystąpieniem B
i funkcji two
, przekazując dodatkowy argument (self
), że nie two
zaakceptować. Zasadniczo, na Pythonie 3, staticmethod
jest wygodą pozwalającą wywołać funkcję na instancjach bez powodowania wiązania, ale jeśli tylko wywołasz tę funkcję odwołując się do samej klasy, nie jest to potrzebne, ponieważ jest to zwykła funkcja, a nie Python 2 "metoda niezwiązana".
Jeśli miał jakieś powody, aby wykonać tę kopię (normalnie sugeruję dziedziczenie z A
, ale cokolwiek), i chcesz, aby upewnić się uzyskać deskryptora owinięte w wersji z funkcji, co nie daje Ci deskryptor kiedy dostępne na A
, można ominąć przez protokół deskryptora bezpośredniego dostępu A
„s __dict__
:
class B(object):
one = A.__dict__['one']
two = A.__dict__['two']
kopiując bezpośrednio ze słownika klasy, magia protokół deskryptor nie jest wywoływany, a otrzymasz staticmethod
i classmethod
opakowane wersje one
i two
.
Wielkie dzięki za informacyjną odpowiedź! Przypadek użycia to pakiet testowy: https://github.com/al4/python-checkrunner/blob/master/tests/test_checkrunner.py Chciałem ponownie użyć tych funkcji i pogrupować je w jedną klasę, aby uniknąć skarg składanych przez PyCharm. dekoratorzy spoza klasy. Najlepszym podejściem jest, jak sądzę, ręczne wywołanie staticmethod z klasą "sub". –
@AlexForbes: W takim przypadku zaimplementowałbym klasę wspólnych funkcji i użyłbym jej jako mixin w klasach, które ich potrzebują. 'class CommonTests (object): ... define jeden, two ...', a następnie miksuj go przez dziedziczenie wielu: 'class A (unittests.TestCase, CommonTests): ... Konkretne testy ...', a następnie 'klasa B (unittests.TestCase, CommonTests): ... specyficzne testy B ...'. Teraz wszystkie metody CommonTests są dziedziczone automatycznie w 'A' i' B', bez konieczności przypisywania ich indywidualnie. Klasa mixin nie dziedziczy po 'TestCase', więc nie będzie testowana samodzielnie. – ShadowRanger