2011-08-01 18 views
7

Próbuję utworzyć (nie do końca przywrócić) obiekt, którego atrybuty zostały zapisane w bazie danych. Dlatego nie chcę dzwonić pod numer __init__. To pragnienie wydaje się być zgodne z Guido's intended use for __new__. Nie rozumiem, dlaczego __init__ nie jest wywoływana.Dlaczego funkcja __init__ nie jest wywoływana, jeśli funkcja __new__ została wywołana bez argumentów:

Weź przykładowy fragment, który zwraca instancję klasy Użytkownik bez wywoływania __init__.

class User(object): 
    def __init__(self, arg1, arg2): 
     raise Exception 

user = User.__new__(User) 

print user 
<project.models.User object at 0x9e2dfac> 

To jest dokładnie to, czego pragnę. Jednak moje pytanie jest takie, że nie rozumiem, dlaczego?

Zgodnie z python docs__init__ ma zostać wywołany, gdy "__new__" zwraca instancję cls. "

Dlaczego więcnie jest wywoływany, mimo że __new__ zwraca instancję klasy?

+1

Proszę napisać kod, który faktycznie działa. Czy chodziło Ci o "def __init__"? –

+0

Natknąłem się na to samo i przekonałem się, że ten pyton tego nie robi. Jednak doktorzy wyraźnie mówią: "Jeśli __new __() zwraca instancję cls, to metoda __init __() nowej instancji będzie wywoływana jak __init __ (self [, ...])". Czy to błąd doktora, czy też błędnie go interpretuję? – UsAaR33

+1

@ UsAaR33 Źle to interpretujesz. Wywołanie 'SomeClass (args)' spowoduje (zwykle) wykonanie 'instance = SomeClass .__ new __ (SomeClass, args)', a następnie wywołanie 'instance .__ init __ (args)' jeśli 'instance' jest instancją' SomeClass'. Dokumenty mówią o "__new__" w kontekście tej sekwencji, a nie o żadnym czasie, w którym się on wywołuje, ponieważ wywołanie '__new__' bezpośrednio jest jeszcze rzadsze niż potrzeba zdefiniowania go w pierwszej kolejności. – Ben

Odpowiedz

10

konstruktor (User()) jest odpowiedzialny za wywołanie przydzielania (User.__new__()) i inicjator (User.__init__()) po kolei. Ponieważ konstruktor nie jest nigdy wywoływany, inicjator nigdy nie jest wywoływany.

10

Ponieważ omijasz zwykły mechanizm konstrukcyjny, wywołując bezpośrednio kod __new__. Logika __init__-po-__new__ jest w type.__call__ (w CPython patrz funkcja typeobject.c, type_call), więc dzieje się tak tylko wtedy, gdy robisz User(...).

Powiązane problemy