이 주제는 정말 오래되었지만 ... 정말 좋은 질문입니다.
abc는 유형을 지정하는 동안, 즉 type('Derived', (FooClass,), {})
이 실행 중일 때만 추상 메소드를 확인할 수 있기 때문에 작동하지 않습니다. 그 후에 수행되는 setattr은 abc에서 액세스 할 수 없습니다.
그래서, 않은 setattr 실 거예요 작품은 buuut는 ... 이전에 선언 또는 정의되지 않은 클래스의 이름을 주소의 귀하의 문제는 해결 가능 같습니다
내가 당신이 자리를 사용할 수 있습니다 약간의 메타 클래스를 썼다 클래스 정의 외부에서 작성하는 메소드를 결국 얻을 수있는 클래스에 액세스하기위한 "clazz".
그런 식으로 abc에서 더 이상 TypeError를 얻지 못할 것입니다. 이제 유형을 설명하기 전에 메소드를 정의한 다음 dict 인수에 입력하십시오. 그러면 abc는 적절한 메소드 오버라이드로 간주합니다.
새 메타 클래스를 사용하면 해당 메서드에서 클래스 개체를 참조 할 수 있습니다. 그리고 이것은 슈퍼입니다, 왜냐하면 지금 당신은 슈퍼를 사용할 수 있기 때문입니다!
import abc
import inspect
clazz = type('clazz', (object,), {})()
def clazzRef(func_obj):
func_obj.__hasclazzref__ = True
return func_obj
class MetaClazzRef(type):
"""Makes the clazz placeholder work.
Checks which of your functions or methods use the decorator clazzRef
and swaps its global reference so that "clazz" resolves to the
desired class, that is, the one where the method is set or defined.
"""
methods = {}
def __new__(mcs, name, bases, dict):
ret = super(MetaClazzRef, mcs).__new__(mcs, name, bases, dict)
for (k,f) in dict.items():
if getattr(f, '__hasclazzref__', False):
if inspect.ismethod(f):
f = f.im_func
if inspect.isfunction(f):
for (var,value) in f.func_globals.items():
if value is clazz:
f.func_globals[var] = ret
return ret
class MetaMix(abc.ABCMeta, MetaClazzRef):
pass
class FooClass(object):
__metaclass__ = MetaMix
@abc.abstractmethod
def FooMethod(self):
print 'Ooops...'
#raise NotImplementedError()
def main():
@clazzRef
def BarOverride(self):
print "Hello, world! I'm a %s but this method is from class %s!" % (type(self), clazz)
super(clazz, self).FooMethod() # Now I have SUPER!!!
derived_type = type('Derived', (FooClass,), {'FooMethod': BarOverride})
instance = derived_type()
instance.FooMethod()
class derivedDerived(derived_type):
def FooMethod(self):
print 'I inherit from derived.'
super(derivedDerived,self).FooMethod()
instance = derivedDerived()
instance.FooMethod()
main()
출력은 다음과 같습니다 : = P 나는
이 봐 ... 당신이 너무 그것에 대해 걱정했다 추측 할 수
Hello, world! I'm a <class 'clazz.Derived'> but this method is from class <class 'clazz.Derived'>!
Ooops...
I inherit from derived.
Hello, world! I'm a <class 'clazz.derivedDerived'> but this method is from class <class 'clazz.Derived'>!
Ooops...
클래스의 추상성 클래스 건설 중에 결정됩니다
. 클래스를 생성하는 동안'FooMethod'를 사전에 포함 시키면 어떨까요? –
@SvenMarnach : 실제 예제에서'BarOverride'는 파생 클래스를 바인딩해야합니다. 이후에 함수를 작성하는 것이이 작업을 수행하는 가장 쉬운 방법입니다. – Thanatos
나는 그 점을 이해하지 못한다. "파생 된 클래스를 바인딩해야합니다"라는 의미는 무엇입니까? –