2012-07-24 10 views
11

Jestem overover metody __new__() klasy, aby zwrócić wystąpienie klasy, który ma określony zestaw __init__(). Python wydaje się wywołać w swojej klasie pod warunkiem __init__() metody zamiast metody specyficzne dla instancji, chociaż dokumentacji Pythona wDlaczego metoda wywołania instancji Pythona nie __init __() podczas tworzenia instancji, ale zamiast tego wywołuje metodę __init __() dostarczoną przez klasę?

http://docs.python.org/reference/datamodel.html

mówi:

Typowe implementacje utworzyć nową instancję klasy przez Wywołanie metody __new __() klasy superklasy przy użyciu super (currentclass, cls) .__ new __ (cls [, ...]) z odpowiednimi argumentami, a następnie zmodyfikowanie nowo utworzonej instancji jako niezbędnej przed jej zwróceniem.

Jeśli __new __() zwraca instancję CLS, a następnie nowej instancji za __init __() metoda zostanie wywołany jak __init __ (ja [...]), gdzie jaźń jest nowa instancja i pozostałe argumenty są taki sam jak przekazano do __new __().

Oto mój kodu testu:

#!/usr/bin/env python 

import new 

def myinit(self, *args, **kwargs): 
    print "myinit called, args = %s, kwargs = %s" % (args, kwargs) 


class myclass(object): 
    def __new__(cls, *args, **kwargs): 
     ret = object.__new__(cls) 

     ret.__init__ = new.instancemethod(myinit, ret, cls) 
     return ret 

    def __init__(self, *args, **kwargs): 
     print "myclass.__init__ called, self.__init__ is %s" % self.__init__ 
     self.__init__(*args, **kwargs) 

a = myclass() 

który wyprowadza

$ python --version 
Python 2.6.6 
$ ./mytest.py 
myclass.__init__ called, self.__init__ is <bound method myclass.myinit of <__main__.myclass object at 0x7fa72155c790>> 
myinit called, args =(), kwargs = {} 

Wydaje się, że jedynym sposobem, aby dostać myinit() do uruchomienia, jest to nazwać jednoznacznie jako self.__init__() wewnątrz myclass.__init__().

+1

Dobre pytanie! – Marcin

Odpowiedz

8

Specjalne metody na zajęciach w nowym stylu są wyglądał na typie instancji, a nie na samej instancji. To documented behaviour:

Dla klas w nowym stylu, ukryte wywołania specjalnych metod są gwarantowane tylko pracować prawidłowo, jeśli określono typu obiektu, a nie w słowniku instancji obiektu.Że zachowanie jest powód, dlaczego następujący kod podnosi wyjątek (w przeciwieństwie do np równoważny z klasami w starym stylu):

>>> class C(object): 
...  pass 
... 
>>> c = C() 
>>> c.__len__ = lambda: 5 
>>> len(c) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: object of type 'C' has no len() 
8

Różne specjalne metody (w tym __init__, ale także przeciążenia operatorów, takie jak __add__, itp.) To always accessed via the class rather than the instance. Nie tylko, ale nie można uzyskać do nich dostępu za pomocą metody __getattr__ lub __getattribute__ na klasie lub metaklasy, muszą one być bezpośrednio w klasie. To ze względu na efektywność:

Omijanie maszyny w ten sposób __getattribute__() zapewnia znaczny zakres dla optymalizacji prędkości w tłumacza, kosztem pewnej elastyczności w obsłudze specjalnych metod (szczególna metoda musi być ustawiony na sam obiekt klasy, aby być konsekwentnie wywoływanym przez interpreter).

To nie jest do końca jasne, co próbujesz osiągnąć, ale jedno można zrobić tutaj jest do podklasy myclass w metodzie __new__:

class myclass(object): 
    def __new__(cls, *args, **kwargs): 
     class subcls(cls): 
      def __new__(cls, *args, **kwargs): 
       return object.__new__(cls) 
     subcls.__init__ = myinit 
     return subcls(*args, **kwargs) 
Powiązane problemy