2009-12-08 5 views
4

개체를 인스턴스화 할 때 개체가 파생되는 클래스를 전달할 수 있습니까? 예를 들어개체의 수퍼 클래스를 __init__에 설정 하시겠습니까?

: Circle의 다른 인스턴스에 영향을 미치는 그러나없이

class Circle(Red): 
    def __init__(self): 
     self.x() 

:

class Red(object): 
    def x(self): 
     print '#F00' 

class Blue(object): 
    def x(self): 
     print '#00F' 

class Circle(object): 
    def __init__(self, parent): 
     # here, we set Bar's parent to `parent` 
     self.x() 

class Square(object): 
    def __init__(self, parent): 
     # here, we set Bar's parent to `parent` 
     self.x() 
     self.sides = 4 

red_circle = Circle(parent=Red) 
blue_circle = Circle(parent=Blue) 
blue_square = Square(parent=Blue) 

은 유사한 효과를 가질 것이다. 당신이 정말로 그것을 필요하면

#!/usr/bin/env python 
class Foo(object): 
    def x(self): 
     print('y') 

def Bar(parent=Foo): 
    class Adoptee(parent): 
     def __init__(self): 
      self.x() 
    return Adoptee() 
obj=Bar(parent=Foo) 
+3

이 방법으로 구성 하시겠습니까? 원과 스퀘어에는 '색상'속성이 있어야합니다. 최소한 일반 영어의 경우, 빨강과 파랑은 서클과 사각형의 부모가 아닙니다. – unutbu

+2

나는 당신이 근본적인 방법으로 "OO 디자인"을 남용하고 있다고 생각합니다. –

+0

@ S.Lott - 나는 지나치게 영리 해 지려고 노력했다. 의존성 주입은 내 작업에 충분할 것입니다. –

답변

4

나는 @AntsAasma에 동의합니다. dependency injection을 사용하는 것이 좋습니다. 주어진 예제에서 (분명히 귀하의 문제를 설명하기 위해 크게 단순화되어 있음), 모양의 색상은 is-a relationship이 아닌 has-a relationship을 통해 더 잘 표현됩니다.

원하는 색상 개체를 생성자에 전달하고 해당 색상 개체에 대한 참조를 저장하고이 개체에 함수 호출을 위임하여 구현할 수 있습니다. 이것은 원하는 동작을 유지하면서 구현을 크게 단순화합니다.

class Red(object): 
    def x(self): 
     print '#F00' 

class Blue(object): 
    def x(self): 
     print '#00F' 

class Shape(object): 
    def __init__(self,color): 
     self._color=color 
    def x(self): 
     return self._color.x() 

class Circle(Shape): 
    def __init__(self, color): 
     Shape.__init__(self,color) 
     self.x() 

class Square(Shape): 
    def __init__(self, color): 
     Shape.__init__(self,color) 
     self.x() 
     self.sides = 4 

red_circle = Circle(color=Red()) 
blue_circle = Circle(color=Blue()) 
blue_square = Square(color=Blue()) 

편집 : 예를 들면 다음과 같습니다 참조 샘플 코드 생성자 인자의 고정 이름을

+0

+1 : mixins a/k/a "Dependency Injection" –

+0

+1. Square의 def __init__에서'parent'는'color'로 변경되어야합니다. – unutbu

+0

@ ~ unutbu : init 인자 이름을 고정 시켜라. –

7

아마도 당신을 위해 무엇을 찾고있는 클래스 공장 공장 함수 내에서 (또는 __new__ 방법 안에, 그러나 이것은 아마도 안전한 방법입니다) : 당신이 그것을 의미하지 않는 무언가를 위해 상속을 사용하려고하는 것처럼 소리

class Foo(object): 
    def x(self): 
     print 'y' 

class Bar(object): 
    def __init__(self): 
     self.x() 

def magic(cls, parent, *args, **kwargs): 
    new = type(cls.__name__, (parent,), cls.__dict__.copy()) 
    return new(*args, **kwargs) 

obj = magic(Bar, parent = Foo) 
0

, 다음 type 생성자를 사용할 수 있습니다, 예를 들면 :

1

. 왜 그렇게하고 싶은지를 설명하면 어쩌면 목표를 성취하기위한 더 관용적이고 강력한 방법을 찾을 수 있습니다.

+0

귀하의 제안에 따라 제 질문이 업데이트되었습니다. –

+2

조금 더 자세히 설명해 주시겠습니까? 귀하의 목표는 자신의 색상을 인쇄하는 도형을 만드는 것이 아니라고 가정합니다. 다른 클래스가 동적으로 제공된 "부모 클래스"가 제공하는 메서드를 확인해야합니까? "부모 클래스"가 자식 객체의 속성/메소드에 액세스해야합니까? 현재 정보가 주어지면 색상의 인스턴스를 속성으로 저장하고 해당 속성을 통해 작업을 위임하는 것이 좋습니다. –

0

다른 사람들이 말했듯이, 그것은 당신이 정말로 그것을 원한다면, 그것을 제외하고 (반드시 실현의 꽤 이상한 사용하지만 신비한 Bar 당신이 코멘트에서 희미한 공기를 끌어 낸다 ;-). 예를 들어 :이 Circle 자신의 개인 클래스 (모든 Circle 이름,하지만 모두 다른)의 각 인스턴스를 제공

class Circle(object): 
    def __init__(self, parent): 
     self.__class__ = type('Circle', (self.__class__, parent), {}) 
     self.x() 

-이 부분은 "은을 할 때이 관용구가 (때로는 매우 유용합니다 중요한 이유는 실제로 새로운 스타일의 클래스를 사용하여 인스턴스 별 맞춤형 특수 메소드를 만들 수 있습니다. 특수 메소드는 항상 클래스에서 조회되므로 인스턴스마다 사용자 정의 할 수 있으므로 각 인스턴스마다 고유 한 클래스가 있어야합니다. 클래스 이름을 사용하여,

_memo = {} 
def classFor(*bases): 
    if bases in _memo: return _memo[bases] 
    name = '_'.join(c.__name__ for c in bases) 
    c = _memo[bases] = type(name, bases, {}) 
    return c 

을 (여기에서 나는 또한 그 결과 클래스의 이름에 대한 다른 접근 방식을 사용하고 있습니다 : 당신은 오히려 조금 memoizing 공장 기능이 도움이 할 수 있습니다 가능한 한 많은 클래스 공유를 할 줄 경우 예를 들어 Circle이 아닌 Circle_RedCircle_Blue과 같은 값일 수 있습니다. 그런 다음 :

class Circle(object): 
    def __init__(self, parent): 
     self.__class__ = classFor(Circle, parent) 
     self.x() 

그래서 기술이 부드럽고 견고하지만, 난 여전히 당신이 예시 유스 케이스에 좋은 경기로 표시되지 않습니다. 그러나 다른 유스 케이스에서는 유용 할 수 있으므로 보여줄 것입니다.

+0

Alex,'TypeError : __class__이 (가) 'classFor'를 사용하는'Circle '의 두 번째 정의를 시도 할 때'NoneType '객체가 아닌 새로운 스타일 클래스로 설정되어야합니다. 나는 틀린 것이 확실하지 않다. 좀 봐 주시겠습니까? – unutbu

+1

죄송합니다. classFor 함수는'return c '만 입력하면됩니다. – unutbu

+0

입력란이 잘못되어 미안합니다. @unutbu, tx를 찾아내는 것이 좋습니다. –

관련 문제