2010-07-07 2 views
7

다음 코드는 파이썬 3.x를 작동하지 않지만, 이전 스타일 클래스와 함께 작동하는 데 사용 :__bases__가 작동하지 않습니다! 무엇 향후 계획?

class Extender: 
    def extension(self): 
     print("Some work...") 

class Base: 
    pass 

Base.__bases__ += (Extender,) 

Base().extension() 

질문은 간단하다 :이 어떻게 (런타임에) 동적으로 추가 할 수 있습니다 파이썬 3.x의 수퍼 클래스?

하지만 답이 어려울 준비가되었습니다.)

+9

귀하의 기지는 더 이상 당신 소유의 것이 아닙니까? 그리고 대답은 어려울 것입니까? – Borealid

+0

필자는 모든 클래스가 파이썬 3에서 새로운 스타일의 클래스이고, Base가'object'와'Extender'를 기본 클래스로 가졌다면 MRO가 모호해지기 때문에 더 이상 불가능하다고 생각합니다. 대신에'Base'와'Extender'를 상속받은 새로운 클래스를 생성하십시오. 'Extender'는 ABC 일 수도 있습니다. – Philipp

답변

4

나를 위해 그것은 불가능합니다. 하지만 당신은 동적으로 새로운 클래스를 만들 수 있습니다

class Extender(object): 
    def extension(self): 
     print("Some work...") 

class Base(object): 
    pass 

Base = type('Base', (Base, Extender, object), {}) 
Base().extension() 
+0

감사합니다! 당신의 솔루션은 잘 작동합니다! :) 하지만 조금 업데이트했습니다 : $ 새로운 기본 클래스 만 추가하면 충분합니다 :'Base = type ('Base', (Extender,), {})' 'Base'와 'object '클래스에서 다시 MRO에서 두 번 나타날 것이며 통역사는 천천히 속성을 찾습니다. – DenisKolodin

+0

@DenisKolodin : MRO의 두 가지 기본 클래스는 새 클래스와 이전 클래스입니다. 그것들이 다른지보기 위해'[id (cls) for Base .__ mro __]'를보십시오. – unutbu

+0

완전히 테스트 한 결과 심각한 차이가 하나 발견되었습니다. (( 유형이 새 인스턴스에만 변경되지만 __bases__을 사용하면 필요한 기존 인스턴스의 속성을 변경할 수 있음) 이 솔루션은 유사하지 않습니다! ( – DenisKolodin

3

object가 아닌 Base.__bases__ Base.__base__ 경우 동적으로 변경하는 것이 가능하다는 것을 나타납니다. (동적으로 변경한다는 의미는 Base에서 상속받은 모든 기존 인스턴스도 동적으로 변경된다는 의미입니다. 그렇지 않은 경우 Mykola Kharechko's solution 참조). Base.__base__ 일부 더미 클래스 TopBase 경우

Base.__bases__에 할당 작동하는 것 같다 :

class Extender(object): 
    def extension(self): 
     print("Some work...") 

class TopBase(object): 
    pass 

class Base(TopBase): 
    pass 

b=Base() 
print(Base.__bases__) 
# (<class '__main__.TopBase'>,) 

Base.__bases__ += (Extender,) 
print(Base.__bases__) 
# (<class '__main__.TopBase'>, <class '__main__.Extender'>) 
Base().extension() 
# Some work... 
b.extension() 
# Some work... 

Base.__bases__ = (Extender, TopBase) 
print(Base.__bases__) 
# (<class '__main__.Extender'>, <class '__main__.TopBase'>) 
Base().extension() 
# Some work... 
b.extension() 
# Some work... 

이 (새로 만들기 및 이전 스타일 클래스) 파이썬 2에서 작동하도록 테스트 및 파이썬 3되었다. 나는 이것이 작동하지 않는 이유는 모르겠다.

class Extender(object): 
    def extension(self): 
     print("Some work...") 

class Base(object): 
    pass 

Base.__bases__ = (Extender, object) 
# TypeError: __bases__ assignment: 'Extender' deallocator differs from 'object' 
+0

Base .__ base__를 값 (object,)에서 (object, Extender)로 변경하려고했기 때문에 "consistent ...를 만들 수 없습니다."라는 오류의 이유가 있습니다. (비슷한 말로'class X (object, Extender)'라고 말할 수는 없다.) 그러나'Base .__ bases__ + = (Extender, +) Base .__ bases__ ''E '를 그냥 던져 버릴 것입니다.' '객체와 다릅니다.' '또 다른 오류가 있지만 여전히 오류입니다. – driax

+0

@driax : 예, 설명해 주셔서 감사합니다 – unutbu

+2

용 나중에 참조, deallocator 오류에 관한 공개 된 CPython 문제가 있습니다 : https://bugs.python.org/issue672115 (2003 년부터 오픈하므로 숨을 멈추지 마십시오) – driax