2014-10-06 4 views
1

:Python 3에서 kwargs와 상속은 어떻게 작동합니까? 다음 샘플 코드 고려

#!/usr/bin/python3 

class Parent: 
    def __init__(self, **kwargs): 
     # Expect data1, data2 
     self.values = kwargs 

    # Accessor method to set object values 
    def setvalue(self, k, v): 
     self.values[k] = v 

    # Accessor method to get/return object values 
    def getvalue(self, k): 
     return self.vlaues.get(k, None) 

class Child(Parent): 
    def __init__(self, **kwargs): 
     # Expect data3, data4 
     self.values = kwargs 

    # Accessor method to set object values 
    def setvalue(self, k, v): 
     self.values[k] = v 

    # Accessor method to get/return object values 
    def getvalue(self, k): 
     return self.values.get(k, None) 

def main(): 
    new_object = Child(data1 = 'abc', data2 = 'def', 
     data3 = 'ghi', data4 = 'jkl') 

    for v in new_object.values: 
     print('{}: {}'.format(v, new_object.getvalue(v))) 

    new_object.setvalue('data1', 'tuv') 
    new_object.setvalue('data4', 'xyz') 

    for v in new_object.values: 
     print('{}: {}'.format(v, new_object.getvalue(v))) 

if __name__ == "__main__": main() 

나는 여전히 몇 가지 기본적인 상속을 사용하는 동안이 kwargs의 flexibity을 활용할 수있는 방법을 궁금하네요. 실제로 쓰는 실제 응용 프로그램에는 각 클래스에는 실제로 여러 가지 특성이 있습니다.

내 관심사는 kwargs 너무 유연한 (그리고 성운)이기 때문에, 나는 내 수업의 부모 - 자식 관계를 유지할 수 있다는 것입니다 - data1, data2, data3, 그리고 data4 모든 Child 클래스에 적용 얻을 것이다 .

어떻게 data1data2Parent 슈퍼 클래스의 속성이 있는지 확인 않으며, data3data4Child 서브 클래스의 속성이 있다고?

코드를 다소 단순하고 우아하게 유지하면서 올바른 방식으로 클래스 구조를 디자인하려고합니다. 그건 상관 없니? 어쩌면 나는 이것에 대한 잘못된 길로 갈 것입니다. 이 작업을 수행하는 더 좋은 방법이 있습니까?

만약 내가 여기에서 어슬렁 거리면 미안. 이해하려고 애를 써. 귀하의 도움과 인내에 미리 감사드립니다 ...

+2

Parent 클래스의 특성과 Child 클래스의 특성 사이를 구별하는 것은 의미가 없습니다. 어떤 언어로든 상속의 전체 요점은 아이가 * 부모라는 것입니다. –

답변

4

첫 번째 문제는 실제로 애초에 속성을 생성하지 않는다는 것입니다. 속성을 원하면 속성을 작성하십시오. 키 - 값 매핑을 원할 경우 매핑을 만듭니다. 여러분이 만든 것은 비표준 API를 사용한 특수 목적의 제한된 기능 매핑입니다. 그럴만한 이유가 없습니다. 당신이 뭔가 뭔가의 속성 있는지 확인하려면

, 그것은 (어떤 경우에는 당신이 setattr 또는 self.__dict__.update 함께 할 있지만) 일반적 self.spam = eggs 과제와는 처음부터 속성, 수있다.


어떻게 그 데이터 1을 확인 않으며, 데이터 2는 상위 슈퍼 클래스의 속성, 그리고 그 데이터 3 및 DATA4는 아동 서브 클래스의 속성인가?

클래스의 invariants의 일부인 것을 보장하려면 각 클래스에서 명시 적으로 보장하고 남은 인수를 super과 함께 전달해야합니다. 예를 들면 :

class Parent: 
    def __init__(self, **kwargs): 
     self.data1 = kwargs.pop('data1', None) 
     self.data2 = kwargs.pop('data2', None) 
     super().__init__(**kwargs) 

class Child(Parent): 
    def __init__(self, **kwargs): 
     self.data3 = kwargs.pop('data3', None) 
     self.data4 = kwargs.pop('data4', None) 
     super().__init__(**kwargs) 

하지만 당신은 당신이 정말로 여기에 여분의 일반성 중 어떤 혜택을받지 못하고 있다는 것을 알 수 있습니다; 당신은-수 있습니다 아마 이런 같은 일을 쓰기 should- :

class Parent: 
    def __init__(self, *, data1=None, data2=None, **kwargs): 
     super().__init__(**kwargs) 
     self.data1 = data1 
     self.data2 = data2 

class Child(Parent): 
    def __init__(self, *, data3=None, data4=None, **kwargs): 
     super().__init__(**kwargs) 
     self.data3 = data3 
     self.data4 = data4 

모든 즉, 당신이 처음에 오해에서 운영하고 생각했다되고 :

내 관심은 kwargs가 매우 융통성이 있기 때문에 클래스의 부모 - 자식 관계를 유지할 수 없다는 것입니다. data1, data2, data3 및 data4는 모두 Child 클래스에 적용됩니다.

아니,이 속성 중 어느 것도 중 하나 클래스에 적용되지되고있다. 그것들은 Child의 모든 인스턴스에 적용됩니다. 그러나 Parent 인스턴스 또는 Child 인스턴스로 해당 속성을 가져 왔는지에 대해서는 의문의 여지가 없습니다. 그들은 단지 __dict__self.spam = eggs 할당을 가진 객체가되어 그들을 얻었다. 인스턴스를 Parent 또는 Child으로 보더라도 구성 후에 오랫동안 추가하는 임의의 추가 특성 또는 object에서 상속 한 표준 특성 또는 그 밖의 특성이있을 수 있습니다.

당신이 정말로, 정말로 단지 datadata2Child 인스턴스되지 않은 Parent 인스턴스를 시행 할 경우, 당신은 여기에 간단하고 명확한 이후 __slots__, @property가 명시 적 설명이 ...,의 처음을하자로 그렇게 할 수 있습니다 :

class Parent: 
    __slots__ = ('data1', 'data2') 
    def __init__(self, **kwargs): 
     self.data1 = kwargs.pop('data1', None) 
     self.data2 = kwargs.pop('data2', None) 
     super().__init__(**kwargs) 

class Child(Parent): 
    __slots__ = ('data3', 'data4') 
    def __init__(self, **kwargs): 
     self.data3 = kwargs.pop('data3', None) 
     self.data4 = kwargs.pop('data4', None) 
     super().__init__(**kwargs) 

지금, 그것은 실제로 Child처럼 data3 슬롯을 추가하는 일부 서브 클래스의 인스턴스가 아니면, AttributeError를 제기하는 Parent 인스턴스에서 data3 속성을 할당하려는 시도.

+0

@ dano : 예, 오타; 그것을 잡아 주셔서 감사합니다, 지금 고쳐. – abarnert

+0

철저한 피드백에 감사드립니다. 나의 주요 목표는 클래스와 서브 클래스 (일반적으로 파이썬 관점에서)를 생성 할 때 올바른 접근법을 이해하는 것이다. 감사합니다. – drwtod

+0

오. 그리고 그래 ... * duh * ... 나는 클래스와 클래스의 차이점을 알 수있다. 나는 왼쪽 필드에서 일종의 아웃이었다. – drwtod