최근 메타 클래스에서 파생 클래스 메서드를 호출하는 중 문제가 발생했습니다.파이썬에서 classmethod를 파생시키는 올바른 방법은 무엇입니까?
class testMetaA(type):
def __init__(cls,cname,bases,cdict):
print "in testMetaA: %s"%cls
그런 다음 나는 메타 클래스를 사용할 수 있습니다 예를 들어, 나는 실제로 인쇄 CLS를 제외한 아무것도하지 메타 클래스를 구축 do1(a)
class testA(object):
@classmethod
def do1(cls, a):
print "in testA:",cls, a
그런 다음 classmethod를 가지고 간단한없는 baseclass testA
를 얻을 예상대로 작동하는 하위 클래스 testB
을 작성하십시오.
class testB(testA):
@classmethod
def do1(cls, a):
print "in testB: %s"%cls
super(testB, cls).do1(a)
__metaclass__=testMetaA
인쇄 할 항목 : in testMetaA: <class '__main__.testB'>
; 와 같은 testB.do1(a)
작품은 예상 :
>>> testB.do1('hello')
in testB: <class '__main__.testB'>
in testA: <class '__main__.testB'> hello
그러나, 나는 testMetaB
다음으로 "super
"를 포함하는 메타 클래스 내부의 classmethod를 호출하려고하면, 에러 올릴 것이다 : NameError: global name 'testC' is not defined
합니다.
class testMetaB(type):
def __init__(cls,cname,bases,cdict):
print "in testMetaB: %s"%cls
cls.do1("hello")
class testC(testA):
@classmethod
def do1(cls, a):
print "in testC: %s"%cls
super(testC, cls).do1(a)
__metaclass__=testMetaB
내가 마지막으로 사용
super(cls, cls)
대신
super(testC, cls)
에 의해 그것을 해결하는 방법을 찾을 수
:
class testD(testA):
@classmethod
def do1(cls, a):
print "in testD: %s"%cls
super(cls, cls).do1(a)
__metaclass__=testMetaB
그것은 인쇄됩니다 같은 :
in testMetaB: <class '__main__.testD'>
in testD: <class '__main__.testD'>
in testA: <class '__main__.testD'> hello
testD.do1(a)
는 예상대로 작동합니다
>>> testD.do1('Well done')
in testD: <class '__main__.testD'>
in testA: <class '__main__.testD'> Well done
이제 classmethod에서 super를 사용하는 가장 올바른 방법이 궁금합니다. 현재 클래스 이름을 명시 적으로 작성하는 대신 항상 super(cls,cls)
을 사용해야합니까?
감사합니다.
@jsbueno
If some piece of code resorts to tricks like dynamically creating derived classes, that is important - one should not use the class name as first parametere to Super if that name is assigned to another object than the class itself. Instead, cls for class methods, or
self.__class__
for instance methods can be passed to Super.
이는 일반적으로 슈퍼에 클래스 이름을 사용하는 나쁜 생각을 의미합니까?
나에게 일반적으로 정상적인 방법으로 super(type(self.__class__),self)
대신 super(type(self),self)
을 사용합니다. self.__class__
을 사용하는 데 큰 이점이 있는지 여부는 알 수 없습니다. @jsbueno 예제를 이와 같이 반복합니다. 여기서 C는 super(type(self),self)
입니다. 따라서 D2()
은 클래스 C
이 변경되는 동안 동작을 변경하지 않습니다.
>>> class A(object):
def do(self):
print "in class A"
>>> class B(A):
def do(self):
super(B, self).do()
>>> class C(A):
def do(self):
super(type(self),self).do()
>>> D1=B
>>> D2=C
>>> D1().do()
in class A
>>> D2().do()
in class A
>>> class B(A):
def do(self):
print "in new class B"
>>> D1().do()
Traceback (most recent call last):
File "<pyshell#52>", line 1, in <module>
D1().do()
File "<pyshell#37>", line 3, in do
super(B, self).do()
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> class C(A):
def do(self):
print "in new class C"
>>> D2().do()
in class A
는 @Don 질문의 제안에 따라, 나는 여기에 파이썬 버전을 넣어 : sys.version = 2.7.2+ (기본 10 월 4 2011 20시 6분 9초) [GCC 4.6.1]
을
@Don 질문 : 여기
클래스 이름에 바인딩 전역 이름을 보여주는 조각이 슈퍼 무엇이입니다. "당신의 메타 클래스 testMetaA 실제로 클래스를 구축하지 않습니다" 그것은, 당신은 실제로'__init__'에서 함수를 감싸려고 할 수 있습니다. 오버라이드하지 않으면 메타 클래스'__new__ '는 슈퍼 메타 클래스의'__new__'을 사용하지 않는다는 것을 의미하지 않습니다. 온라인에서 많은 예제를 찾을 수 있습니다. 그리고 평범한 클래스에서와 같이, '__new__'의 메타 클래스에 대한 첫 번째 인수는'__init__'의 첫 번째 인수 인 metaclass와 완전히 다르다는 것을 알아야합니다. – Wang클래스 이름이나 기본 튜플을 수정하는 것을 제외하고 항상'__init__'을 고수 할 수 있습니다. '__new__' 이후의'__init__ '안에는 메타 클래스의 인스턴스 cls가 실제로 존재하기 때문에'__new__'보다 더 편리하다고 생각합니다. 왜냐하면'__new__ '안에서'cls = super (testMetaB, meta) .__ new __ (meta, cname, bases, cdict)'를 사용하여 cls를 먼저 만들 수 있습니다. 그런 다음'__new__'에서 수정하십시오. – Wang
나에게'self'는 실제로 정상적인 클래스의 인스턴스를 참조합니다. 나는 보통 metaclass의'__new__'의 첫 번째 인자로'meta'를 사용하고'cls'는 메타 클래스의 인스턴스 (보통 클래스)를 참조합니다. 원하는 단어를 사용할 수 있습니다. 중요하지 않습니다. 어쨌든 내 질문에는 전혀 관련이 없습니다. – Wang