2015-05-21 23 views
5

Czytam o klasach w Pythonie (3.4) iz tego co rozumiem, wydaje się, że każdy nowy obiekt ma swoje własne instancje metod związanych.Czy Python naprawdę tworzy wszystkie powiązane metody dla każdej nowej instancji?

class A: 

    def __init__(self, name): 
     self.name = name 

    def foo(self): 
     print(self.name) 

a = A('One') 
b = A('Two') 

print(a.foo == b.foo) 

Dane wyjściowe to False.

Wydaje mi się to marnowaniem pamięci. Pomyślałem, że wewnętrznie a.foo i b.foo wskazywałoby jakoś wewnętrznie na jedną funkcję w pamięci: A.foo gdzie self jako instancja klasy zostanie przekazana.

Zakładam, że może nie można go łatwo zaimplementować w języku.

Czy każda nowa instancja zawiera również nowe wystąpienia powiązanych metod?

Jeśli tak, czy nie szkodzi to wydajności lub nie czyni przypadku tworzenia nowych obiektów bardziej ostrożnie niż w innych językach, w których metody są "udostępniane" między obiektami takimi jak w Java?

+0

Czy możesz linkować do czegoś, co czytasz, co sprawia, że ​​tak myślisz? –

+0

@SotiriosDelimanolis 'X(). F == X.f' spowoduje" False "(gdzie f jest metodą instace). To wystarczy, aby tak myśleć. –

+0

Każda związana metoda odwołuje się do tej samej podstawowej funkcji. Obciążenie pamięci dla owijki jest minimalne. – chepner

Odpowiedz

14

Metody są powiązane na żądanie, za każdym razem, gdy uzyskujesz dostęp do jednego.

Uzyskiwanie dostępu do nazwy funkcji wywołuje descriptor protocol, która na obiektach funkcji zwraca metodę związaną.

Metoda powiązana to cienkie opakowanie wokół obiektu funkcji; przechowuje odniesienie do oryginalnej funkcji i instancji. Podczas wywoływania obiektu metody, on z kolei przekazuje wywołanie funkcji, z instancją wstawioną jako pierwszy argument.

Metody nie są tworzone podczas tworzenia instancji, więc nie jest wymagana dodatkowa pamięć a priori.

Można odtworzyć kroki ręcznie:

>>> class A: 
...  def __init__(self, name): 
...   self.name = name 
...  def foo(self): 
...   print(self.name) 
... 
>>> a = A('One') 
>>> a.foo 
<bound method A.foo of <__main__.A object at 0x100a27978>> 
>>> a.foo.__self__ 
<__main__.A object at 0x100a27978> 
>>> a.foo.__func__ 
<function A.foo at 0x100a22598> 
>>> A.__dict__['foo'] 
<function A.foo at 0x100a22598> 
>>> A.__dict__['foo'].__get__(a, A) 
<bound method A.foo of <__main__.A object at 0x100a27978>> 
>>> A.__dict__['foo'].__get__(a, A)() 
One 

Jest tylko przedmiotem metoda, która jest odtworzona za każdym razem; funkcja bazowy pozostaje stabilny:

>>> a.foo is a.foo 
False 
>>> b = A('Two') 
>>> b.foo is a.foo 
False 
>>> b.foo.__func__ is a.foo.__func__ 
True 

Architektura ta umożliwia również classmethod, staticmethod i property obiekty działać. Możesz tworzyć własne deskryptory, tworząc cały szereg ciekawych zachowań wiążących.

+0

To również twoja odpowiedź, więc dostaniesz przedstawiciel, którego najwyraźniej nie potrzebujesz więcej, o) – jonrsharpe

+0

@jonrsharpe: hah, ale ten jest już zaakceptowany! :-P Nie wróciłem do tego pytania w całości; z perspektywy czasu zarówno pytanie, jak i odpowiedź są doskonałym duplikatem. Miałem wrażenie, że w drugim poście jest więcej do wyjaśnienia. –

Powiązane problemy