2016-07-30 6 views
1

메타 클래스로 생성 된 모든 클래스에 속성을 추가하고 싶습니다. 예를 들어, C이라는 클래스가 생성되면 C._C__sup 값이 설명자 super(C) 인 속성을 추가하고 싶습니다.파이썬 __super black magic failed

class Meta(type): 
    def __init__(cls, name, bases, dict): # Not overriding type.__new__ 
     cls.__dict__['_' + name + '__sup'] = super(cls) 
     # Not calling type.__init__; do I need it? 

class C(object): 
    __metaclass__ = Meta 

c = C() 
print c._C__sup 

이 저를 제공합니다 : 여기

내가 무엇을 시도했다입니다

TypeError: Error when calling the metaclass bases 
    'dictproxy' object does not support item assignment 

배경 정보 :
이 (당신은이 부분을 읽을 필요가 없습니다)

영감 this article에 의해, 무엇을 내가 뭘하는 super를 사용하는 경우 "하드 코딩"클래스 이름을 방지하기 위해 노력하고있다 :

아이디어는 개인 속성과 결합되지 않은 슈퍼 객체를 사용하는 것이있다.

>>> C._C__sup = super(C) 

구문이 self.__sup.meth 가 대안으로 사용할 수있는 방법 안쪽이 정의와 : 예를 들어, 우리의 예제에서, 우리는 언 바운드 슈퍼 객체 super(C)로 클래스 C의 개인 속성 __sup을 정의 할 수 있습니다 ~ super(C, self).meth. 의 이점은 호출 구문에서 클래스 이름을 반복하지 않아야한다는 것입니다.이 이름은 private 이름의 메커니즘을 통해 숨겨져 있기 때문입니다. __sup 속성의 생성은 메타 클래스에서 숨겨져 자동으로 수행 될 수 있습니다. 그럼,이 모든 것 같습니다 : 그러나 사실이 경우가 아닙니다.

답변

2

사용 setattr 대신 할당 cls.__dict__에 :

class Meta(type): 
    def __init__(cls, name, bases, clsdict): # Not overriding type.__new__ 
     setattr(cls, '_' + name + '__sup', super(cls)) 
     super(Meta, cls).__init__(name, bases, clsdict) 

class C(object): 
    __metaclass__ = Meta 
    def say(self): 
     return 'wow' 

class D(C): 
    def say(self): 
     return 'bow' + self.__sup.say() 

c = C() 
print(c._C__sup) 
# <super: <class 'C'>, <C object>> 
d = D() 
print(d.say()) 

인쇄

그런데
bowwow 

,

 super(Meta, cls).__init__(name, bases, clsdict) 
012를 호출하는 것이 좋습니다

안에 Meta.__init__Meta이 의 체인을 제대로 호출하려면 에 필요할 수있는 클래스 계층 구조에 참여하도록 허용하십시오. 이것은 의 사용을 돕기 위해 메타 클래스를 빌드하기 때문에 특히 적합합니다. super입니다.