Mam klasy Pythona, z których potrzebuję tylko jednej instancji w czasie wykonywania, więc wystarczyłoby mieć atrybuty tylko raz na klasę, a nie na instancję. Jeśli byłoby więcej niż jedno wystąpienie (co się nie stanie), wszystkie wystąpienia powinny mieć tę samą konfigurację. Zastanawiam się, która z poniższych opcji byłaby lepsza lub bardziej „idiomatyczna” w Pythonie.
Zmienne klasowe:
class MyController(Controller):
path = "something/"
children = [AController, BController]
def action(self, request):
pass
Zmienne instancji:
class MyController(Controller):
def __init__(self):
self.path = "something/"
self.children = [AController, BController]
def action(self, request):
pass
Odpowiedzi:
Jeśli i tak masz tylko jedną instancję, najlepiej ustawić wszystkie zmienne na instancję, po prostu dlatego, że będą dostępne (trochę) szybciej (o jeden poziom „wyszukiwania” mniej ze względu na „dziedziczenie” z klasy do instancji), i nie ma żadnych wad, aby ważyć tę małą przewagę.
źródło
python -mtimeit
- ale właśnie to zrobiłem w pythonie3.4 Zauważyłem, że dostęp doint
zmiennej klasy jest w rzeczywistości około 5 do 11 nanosekund szybciej niż ta sama zmienna instancji na mojej starej stacji roboczej - nie jestem pewien, co codepath sprawia, że tak jest.Dalsze powtórzenie rady Mike'a i Alexa i dodanie własnego koloru ...
Używanie atrybutów instancji jest typowym ... bardziej idiomatycznym Pythonem. Atrybuty klas nie są używane tak często, ponieważ ich przypadki użycia są specyficzne. To samo dotyczy metod statycznych i klasowych oraz metod „normalnych”. Są to specjalne konstrukcje odnoszące się do konkretnych przypadków użycia, w przeciwnym razie jest to kod stworzony przez anormalnego programistę, który chce się pochwalić, że zna jakiś niejasny zakątek programowania w Pythonie.
Alex wspomina w swojej odpowiedzi, że dostęp będzie (trochę) szybszy dzięki o jeden mniejszy poziom wyszukiwania ... pozwólcie, że wyjaśnię dalej tym, którzy nie wiedzą jeszcze, jak to działa. Jest bardzo podobny do dostępu zmiennego, którego kolejność wyszukiwania jest następująca:
W przypadku dostępu do atrybutów kolejność jest następująca:
Obie techniki działają w sposób „na lewą stronę”, co oznacza, że najpierw sprawdzane są najbardziej lokalne obiekty, a następnie sprawdzane są warstwy zewnętrzne.
W powyższym przykładzie załóżmy, że szukasz
path
atrybutu. Gdy napotka odniesienie takie jak „self.path
”, Python najpierw sprawdzi atrybuty instancji w celu dopasowania. Gdy to się nie powiedzie, sprawdza klasę, z której utworzono obiekt. Na koniec przeszuka klasy bazowe. Jak stwierdził Alex, jeśli twój atrybut zostanie znaleziony w instancji, nie musi szukać gdzie indziej, stąd oszczędność czasu.Jeśli jednak nalegasz na atrybuty klas, potrzebujesz tego dodatkowego wyszukiwania. Lub inną alternatywą jest odwoływanie się do obiektu za pośrednictwem klasy zamiast instancji, np.
MyController.path
Zamiastself.path
. To jest bezpośrednie wyszukiwanie, które obejdzie odroczone wyszukiwanie, ale jak Alex wspomina poniżej, jest to zmienna globalna, więc tracisz ten bit, który myślałeś, że zamierzasz zapisać (chyba że utworzysz lokalne odniesienie do [globalnej] nazwy klasy ).Najważniejsze jest to, że przez większość czasu powinieneś używać atrybutów instancji. Będą jednak sytuacje, w których atrybut klasy będzie odpowiednim narzędziem do tego zadania. Kod używający obu w tym samym czasie będzie wymagał największej staranności, ponieważ użycie
self
zapewni ci dostęp tylko do obiektu atrybutu instancji i cienia do atrybutu klasy o tej samej nazwie. W takim przypadku musisz użyć access atrybutu przez nazwę klasy, aby się do niego odwołać.źródło
MyController
jest wyszukiwany w globalnych, więc całkowity koszt jest wyższy niżself.path
gdziepath
jest zmienna instancji (ponieważself
jest lokalna dla metody == superszybkie wyszukiwanie).W razie wątpliwości prawdopodobnie potrzebujesz atrybutu instancji.
Atrybuty klas najlepiej rezerwować na specjalne okazje, w których mają sens. Jedynym bardzo częstym przypadkiem użycia są metody. Nie jest rzadkością , aby korzystać z atrybutów klasy dla stałych tylko do odczytu, że przypadki trzeba wiedzieć (choć jedyną korzyścią jest to, czy chcesz także dostęp z zewnątrz klasy), ale należy być ostrożnym z pewnością o przechowywanie w nich żadnego państwa , co rzadko jest tym, czego chcesz. Nawet jeśli będziesz mieć tylko jedną instancję, powinieneś napisać klasę tak, jak każdą inną, co zwykle oznacza użycie atrybutów instancji.
źródło
avoid global variables
a ich definicja jest taka, że zmienne globalne są również zmiennymi zadeklarowanymi jako atrybuty klas. Jednak własny przewodnik po stylu Pythona ( PEP-8 ) powinien być pierwszym miejscem do zadawania pytań tego rodzaju. Wtedy Twój własny umysł powinien być narzędziem z wyboru (oczywiście możesz też czerpać pomysły na przykład z Google).To samo pytanie na temat wydajności dostępu do zmiennych klas w Pythonie - kod tutaj zaadaptowany z @Edward Loper
Najszybciej uzyskuje się dostęp do zmiennych lokalnych, które są w dużej mierze powiązane ze zmiennymi modułowymi, po których następują zmienne klasy, a po nich zmienne instancji.
Istnieją 4 zakresy, z których można uzyskać dostęp do zmiennych:
Test:
Wynik:
źródło