2017-12-26 16 views
1

저는 Python으로 작성한 프로젝트의 행렬 작업을하고 있습니다. 행렬을 조작하기 위해 이미 많은 라이브러리가 존재한다는 것을 알고 있지만, 필자는 자체적으로 쓰고 있습니다. 그래서 후드에서 무슨 일이 일어나는지 정확히 알 수 있습니다.부모 클래스 초기화에서 조건에 대한 하위 클래스 초기화

그래서 Matrix 기본 클래스와 Vector 하위 클래스가 있습니다. 둘 다 예상대로 개별적으로 작동하지만 MatrixVector이 한 줄 또는 열로 초기화되어 있으면 좋겠다.

Matrix을 올바른 크기로 초기화하면 self = Vector(...)과 같은 문자를 시도했습니다. 그러나 그것은 그 대상에 영향을 미치지 않는 것 같습니다. 또한 __init__() 메서드를 Vector 클래스로 호출하는 방법을 생각했지만 충분히 중요하지 않은 것은 Vector의 메서드이기 때문에 충분하지 않습니다.

이런 상황을 다루는 파이썬적인 방법이 있습니까?

+0

'__init__'으로 마법을 쓰려고하지 않고, 기준에 따라 클래스를 결정하는 팩토리를 사용하십시오. –

답변

2

이렇게하는 것이 가장 좋은 방법은 아니지만 가능합니다. 결국 Matrix 클래스가 인스턴스화되면 결과는 Matrix 인스턴스로 간주됩니다.

그것을 달성하는 한 가지 방법은 Matrix 클래스의 생성자를 정의하는 것입니다

:

class Matrix: 
    def __new__(cls, nrows, ncols): 
     if nrows == 1: 
      inst = super(Matrix, cls).__new__(Vector) 
     else: 
      inst = super(Matrix, cls).__new__(cls) 
     inst.nrows = nrows 
     inst.ncols = ncols 
     return inst 

    def __repr__(self): 
     return '{}(nrows={}, ncols={})'.format(
      self.__class__.__name__, self.nrows, self.ncols) 

데모 : 인스턴스가 실제로 __new__() 방법 내에서 생성되는

>>> m1 = Matrix(2, 5)                                                                                 
Matrix(nrows=2, ncols=5)                                                                               
>>> Matrix(1, 5)                                                                                 
Vector(nrows=1, ncols=5) 

마음, __init__()가 사용된다 새로 생성 된 인스턴스를 초기화합니다. 또한

, 통화 한 지하지 Vector__init__() 방법과 같은 원치 않는 놀라움을 초래할 수있는 Matrix 클래스를 통해 Vector 인스턴스를 생성, @Blckknght 아래의 코멘트에 언급 한 바와 같이이 (수동으로 호출 할 것이다) .

class Matrix: 
    def __init__(self, nrows, ncols): 
     self.nrows = nrows 
     self.ncols = ncols 

    def __repr__(self): 
     return '{}(nrows={}, ncols={})'.format(
      self.__class__.__name__, self.nrows, self.ncols) 

class Vector(Matrix): 
    pass 

def make_matrix(nrows, ncols): 
    if nrows == 1: 
     return Vector(nrows, ncols) 
    return Matrix(nrows, ncols) 

데모 : : 물론

>>> make_matrix(1, 5) 
Vector(nrows=1, ncols=5) 
>>> make_matrix(2, 5) 
Matrix(nrows=2, ncols=5) 

사용 사례에 따라하지만, 때문에 청결하게 유지하고 단지 인스턴스 생성에 대한 공장를 사용하는 것이 더 좋을 수도 make_matrix()Matrix 클래스의 (클래스/정적) 메서드로 구현 될 수 있지만 부모 클래스를 해당 하위 클래스 중 하나와 더 밀접하게 결합하게됩니다.

+0

이 상황에서'__new__'을 사용하는 것에 대한 한 가지 경고 : 클래스의'__init__' 메소드는 인스턴스는 자체 클래스를 호출하여 만들어집니다. 'Matrix .__ new__'에서'Vector .__ new__'를 호출하여'Vector'의 인스턴스를 생성하면'__init__' 메소드가 호출되지 않습니다. 반면에'Vector'를 직접 호출하려고하면 (Vector를 상속하지 않는다면'Vector'는'Matrix .__ new__'를 상속 받기 때문에) 무한 재귀를 유도 할 것입니다. – Blckknght

+0

이것은 올바른 발언이며, 권장하지 않는 또 다른 이유입니다. 차라리 공장에 가려고합니다. 이것을 언급 해 주셔서 감사합니다. – plamut

+0

고마워요! 나는이'__new__' 방법을 본 적이 없었습니다. 나는 두 가지 방법 모두를 가장 적합한 방법으로 시도 할 것이다.귀하의 공장 솔루션은 가장 무난하고 자연스러운 솔루션이라고 생각합니다. –