나는 외부 라이브러리에 의해 제공되는 클래스가 있습니다. 이 클래스의 하위 클래스를 만들었습니다. 또한 원래 클래스의 인스턴스가 있습니다.Python에서 인스턴스 재구성
이제 인스턴스가 이미 가지고있는 속성을 변경하지 않고이 인스턴스를 내 하위 클래스의 인스턴스로 바꾸고 싶습니다. (내 서브 클래스가 재정의 한 것을 제외하고).
다음 해결책이 효과가있는 것 같습니다.
# This class comes from an external library. I don't (want) to control
# it, and I want to be open to changes that get made to the class
# by the library provider.
class Programmer(object):
def __init__(self,name):
self._name = name
def greet(self):
print "Hi, my name is %s." % self._name
def hard_work(self):
print "The garbage collector will take care of everything."
# This is my subclass.
class C_Programmer(Programmer):
def __init__(self, *args, **kwargs):
super(C_Programmer,self).__init__(*args, **kwargs)
self.learn_C()
def learn_C(self):
self._knowledge = ["malloc","free","pointer arithmetic","curly braces"]
def hard_work(self):
print "I'll have to remember " + " and ".join(self._knowledge) + "."
# The questionable thing: Reclassing a programmer.
@classmethod
def teach_C(cls, programmer):
programmer.__class__ = cls # <-- do I really want to do this?
programmer.learn_C()
joel = C_Programmer("Joel")
joel.greet()
joel.hard_work()
#>Hi, my name is Joel.
#>I'll have to remember malloc and free and pointer arithmetic and curly braces.
jeff = Programmer("Jeff")
# We (or someone else) makes changes to the instance. The reclassing shouldn't
# overwrite these.
jeff._name = "Jeff A"
jeff.greet()
jeff.hard_work()
#>Hi, my name is Jeff A.
#>The garbage collector will take care of everything.
# Let magic happen.
C_Programmer.teach_C(jeff)
jeff.greet()
jeff.hard_work()
#>Hi, my name is Jeff A.
#>I'll have to remember malloc and free and pointer arithmetic and curly braces.
그러나, 나는 마법의 __class__
를 재 할당하는 것은 바로 생각하지 않기 때문에 특히,이 솔루션은 내가 (트리플 부정에 대한 죄송합니다) 생각하지 않은주의 사항을 포함하지 않는 것을 확신 아니에요. 이 방법이 효과가 있다고하더라도, 나는이 일을하는 더 평범한 방법이 있어야한다고 생각합니다.
있습니까?
편집 : 답변 해 주셔서 감사합니다. 여기에 내가 그들로부터 무엇을 얻을 수 있습니다 :
__class__
에 할당하여 인스턴스를 reclassing의 아이디어는 널리 사용되는 관용구는 아니지만, 대부분의 답변을 (4 ~ 6에서 글을 쓰는 시점은) 그것을 유효을 고려 접근. 하나의 답변 (ojrac에 의한)은 "처음에는 꽤 이상한"것이라고 말하면서 동의합니다. (질문하는 이유였습니다). 한 가지 대답 (Jason Baker, 두 가지 긍정적 인 의견이 & 표를 얻음)은이 기술을 사용하지 못하도록 적극적으로 권장하지 않았습니다.긍적 적이든 아니든이 방법 중 실제 기술적 문제는 없습니다. 예외는 거의 있을지도 모르는 예전 스타일의 클래스와 C 확장을주의해야한다는 jls입니다. 나는 새로운 스타일 클래스 인식 C 확장이 Python 자체 (이 코드는 후자라고 가정)가이 메소드와 잘 맞아야한다고 생각하지만, 동의하지 않으면 응답을 계속 가져온다.
얼마나 진절 통성이 있는지에 관해서는 몇 가지 긍정적 인 답변이 있지만 실제 이유는 없습니다. Zen (import this
)을 보면,이 경우 가장 중요한 규칙은 "Explicit은 암묵적인 것보다 낫다"는 것입니다. 그렇긴하지만 그 규칙이 이러한 방식으로 재현되도록 반대하는지 여부에 대해서는 확실하지 않습니다. 우리가 명시 적으로 객체에 우리의 변경을 대신 마법을 사용으로 {has,get,set}attr
를 사용
은 더 명시 적으로 보인다.
__class__ = newclass
을 사용하면 명시 적으로 "이제는 클래스 'newclass의 개체입니다.'는 특성을 자동 변경하는 대신 다른 동작을 기대하지만 개체의 사용자는 일반 개체 구 클래스의
요약 : 기술적 인 관점에서 보면이 방법은 괜찮은 것 같습니다. pythonicity 질문은 "긍정"에 편향되어 답이 없습니다.
Mercurial 플러그인 예제가 매우 강하기 때문에 마틴 가이 슬러의 답변을 수락했습니다 (또한 아직 나 자신에게 묻지 않은 질문에 답변했기 때문에).그러나, pythonicity 질문에 대한 논쟁이 있다면, 나는 여전히 그들을 듣고 싶습니다. 지금까지 모두에게 감사합니다.
P. 실제 사용 사례는 런타임에에 추가 기능 을 성장시켜야하는 UI 데이터 컨트롤 개체입니다. 그러나이 질문은 매우 일반적입니다.
잠깐 ... 뭐라 구요? ... –
좋은 예입니다. 어떤 경우에이 패턴이 유용하다고 설명 할 수 있습니까? 나는 그 아이디어가 마음에 들지만, 어떻게 유용하게 쓰는지 모르겠다. :) – NicDumZ
@ NicDumZ : 질문 주셔서 감사합니다. 그것은 편집에서 응답합니다. – balpha