문제

메타클래스와 다중 상속에 관해 두 가지 질문이 있습니다.첫 번째는 다음과 같습니다.클래스에 대해 TypeError가 발생하는 이유는 무엇입니까? Derived 하지만 그렇지 않다 Derived2?

class Metaclass(type): pass

class Klass(object):
    __metaclass__  = Metaclass

#class Derived(object, Klass): pass # if I uncomment this, I get a TypeError

class OtherClass(object): pass

class Derived2(OtherClass, Klass): pass # I do not get a TypeError for this

정확한 오류 메시지는 다음과 같습니다.

TypeError: Error when calling the metaclass bases Cannot create a consistent method resolution order (MRO) for bases object, Klass

두 번째 질문은 다음과 같습니다.왜? super 이 경우에는 작동하지 않습니다(사용하는 경우 __init__ 대신에 __new__, super 다시 작동합니다):

class Metaclass(type):
    def __new__(self, name, bases, dict_):
        return super(Metaclass, self).__new__(name, bases, dict_)

class Klass(object):
    __metaclass__  = Metaclass

나는 다음을 얻습니다:

TypeError: Error when calling the metaclass bases type.__new__(X): X is not a type object (str)

저는 파이썬 2.6을 사용하고 있습니다.

도움이 되었습니까?

해결책

두 번째 질문은 이미 두 번이나 잘 답변되었습니다. __new__ 실제로 주석에서 잘못 주장된 클래스 메서드가 아닌 정적 메서드입니다...:

>>> class sic(object):
...   def __new__(cls, *x): return object.__new__(cls, *x)
... 
>>> type(sic.__dict__['__new__'])
<type 'staticmethod'>

첫 번째 질문(누군가 언급했듯이)은 메타클래스와 관련이 없습니다.B가 A의 하위 클래스인 경우 이 순서대로 두 클래스 A와 B에서 상속을 곱할 수는 없습니다.예:

>>> class cis(sic): pass
... 
>>> class oops(sic, cis): pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
    Cannot create a consistent method resolution
order (MRO) for bases sic, cis

MRO는 가장 왼쪽 베이스가 가장 오른쪽 베이스보다 먼저 방문되도록 보장합니다. 그러나 조상 중에서 x가 y의 하위 클래스인 경우 x가 y보다 먼저 방문된다는 것도 보장합니다.이 경우 두 가지 보장을 모두 만족시키는 것은 불가능합니다.물론 이러한 보장에는 타당한 이유가 있습니다.그것들 없이(예:메서드 결정에서 왼쪽-오른쪽 순서만 보장하는 이전 스타일 클래스에서는 ~ 아니다 하위 클래스 제약 조건) x의 모든 재정의는 y의 정의를 위해 무시되며 이는 그다지 의미가 없습니다.생각해 보세요:무엇 하다 물려받다라는 뜻이다. object 첫 번째, 그리고 다른 클래스에서 두 번째로?저것 object의(본질적으로 존재하지 않는 ;-) 여러 특수 메서드 정의가 다른 클래스의 정의보다 우선해야 하므로 다른 클래스의 재정의가 무시됩니까?

다른 팁

첫 번째 질문은 살펴보십시오 파이썬에서 MRO에 대한 설명 - 구체적으로, "잘못된 메소드 해상도 순서"섹션. 본질적으로, Python은 물체를 사용할지 또는 Klass의 방법을 사용하는지 모른다는 사실과 관련이 있습니다. (메타 클라스 사용과는 아무런 관련이 없습니다.)

두 번째 질문은 당신이 어떻게 __new__ 기능이 작동합니다. 그것은 첫 번째 논쟁으로 자체를 언급하지 않습니다 - 그것은 인스턴스화되는 클래스의 유형을 참조합니다. 따라서 코드는 다음과 같습니다.

class Metaclass(type):
    def __new__(cls, name, bases, dictn):
        return type.__new__(cls, name, bases, dictn)

두 번째 질문은 __new__ 이와 같이:

class Metaclass(type):
    def __new__(self, name, bases, dict_):
        return super(Metaclass, self).__new__(self, name, bases, dict_)

class Klass(object):
    __metaclass__  = Metaclass

나는 이것이 왜 내 머리 꼭대기에서 기억할 수 없지만, 나는 그것이 왜냐하면 type.__new__ 바운드 방법이 아니므로 자기 주장을 마술처럼 얻지 못합니다.

왜 하시겠습니까?

class Derived(object, Klass):

Klass는 이미 물체에서 파생됩니다.

class Derived(Klass):

여기에 합리적인 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top