2012-07-24 2 views
11

특정 __init__() 집합을 가진 클래스 인스턴스를 반환하려면 클래스의 __new__() 메서드를 오버 라이딩합니다. 파이썬은파이썬은 인스턴스 생성시 인스턴스 메소드 __init __()을 호출하지 않지만 대신 클래스 제공 __init __()를 호출하지 않습니까?

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

에서 파이썬 문서 있지만, 대신 인스턴스 특정 방법의 클래스에서 제공하는 __init__() 메소드를 호출하는 것으로 보인다 말한다 :

일반적인 구현 클래스의 새로운 인스턴스를 생성 super (currentclass, cls) .__ new __ (cls [, ...]) 을 적절한 인수로 사용하여 수퍼 클래스의 __new __() 메소드를 호출 한 다음 새로 생성 된 인스턴스를 반환하기 전에 으로 수정해야합니다. 자기가 새로운 인스턴스이며, 나머지 인수는

__new가 __() CLS의 인스턴스를 돌려주는 경우, 새로운 인스턴스의 __init의 __() 메소드 는 __init __처럼 호출됩니다 (자기 [...]) 동일한 것이 __new __()에 전달되었습니다. myinit() 실행 얻을 수있는 유일한 방법을 보인다 myclass.__init__() 내부 self.__init__()로 명시 적으로 호출하는 것입니다

#!/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() 

$ 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 = {} 

를 출력합니다

여기 내 테스트 코드입니다.

+1

위대한 질문 : 그 문제는 다음 코드 (이전 스타일 클래스와 동등한 예와는 달리) 예외가 발생하는 이유입니다! – Marcin

답변

8

특별 방법 인스턴스 자체가 아닌 인스턴스의 유형에 따라 달라집니다. 이 documented behaviour입니다 :

새로운 스타일의 클래스

은 특별한 방법의 암시 적 호출이뿐만 아니라 객체의 인스턴스 사전에, 객체의 유형에 정의 된 경우 제대로 작동하려면 보장됩니다.

>>> 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

__init__뿐만 아니라 __add__과 같은 연산자 오버로드 등을 포함한 다양한 특수 방법은 always accessed via the class rather than the instance입니다. 뿐만 아니라 클래스 또는 메타 클래스의 __getattr__ 또는 __getattribute__ 메서드를 통해 액세스 할 수 없으므로 클래스에 직접 있어야합니다. 이 방식으로 __getattribute__() 기계를 무시

특별한 방법의 처리에 유연성의 비용으로, 인터프리터 내에서 속도 최적화 상당한 범위를 제공한다 (특별한 방법에 설정해야합니다 :이 효율성의 이유입니다 인터프리터에 의해 일관성있게 호출되기 위해서 클래스 객체 자체).

그것은 당신이 달성하려고하는지 완전히 명확하지 않다,하지만 당신은 여기에서 할 수있는 한 가지가 __new__ 메소드 내 myclass를 서브 클래 싱하는 것입니다 보았다되는 새로운 스타일의 클래스에

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) 
관련 문제