source

슈퍼 사용법 정확함(잘못된 패싱)

ittop 2023. 7. 31. 21:52
반응형

슈퍼 사용법 정확함(잘못된 패싱)

그래서 저는 파이썬의 "유해하다고 생각되는 것"을 따라가서 그의 예를 시험해 보았습니다.

, 올바른 통화 방법을 보여주어야 하는 예 1-3.super취급할 때.__init__서로 다른 주장을 예상하는 방법, 즉 완전한 방식은 효과가 없습니다.

다음과 같은 정보를 얻을 수 있습니다.

~ $ python example1-3.py 
MRO: ['E', 'C', 'A', 'D', 'B', 'object']
E arg= 10
C arg= 10
A
D arg= 10
B
Traceback (most recent call last):
  File "Download/example1-3.py", line 27, in <module>
    E(arg=10)
  File "Download/example1-3.py", line 24, in __init__
    super(E, self).__init__(arg, *args, **kwargs)
  File "Download/example1-3.py", line 14, in __init__
    super(C, self).__init__(arg, *args, **kwargs)
  File "Download/example1-3.py", line 4, in __init__
    super(A, self).__init__(*args, **kwargs)
  File "Download/example1-3.py", line 19, in __init__
    super(D, self).__init__(arg, *args, **kwargs)
  File "Download/example1-3.py", line 9, in __init__
    super(B, self).__init__(*args, **kwargs)
TypeError: object.__init__() takes no parameters

는 것 같습니다.object그 자체는 문서에 언급된 모범 사례 중 하나를 위반합니다. 즉, 다음 방법을 사용합니다.super수락해야 함*args그리고.**kwargs.

자, 분명히 나이트 씨는 자신의 예시가 효과가 있을 것이라고 기대했습니다. 그렇다면 이것이 최근 버전의 파이썬에서 변경된 것일까요?2.6과 2.7을 확인했는데 두 가지 모두 실패했습니다.

그렇다면 이 문제를 다루는 올바른 방법은 무엇일까요?

경우에 따라 두 클래스에 일부 매개 변수 이름이 공통적으로 있을 수 있습니다.이 경우 키-값 쌍을 팝업에서 제거할 수 없습니다.**kwargs또는 에서 제거합니다.*args대신 다음을 정의할 수 있습니다.Base와는 다른 계급object인수 흡수/제거:

class Base(object):
    def __init__(self, *args, **kwargs): pass

class A(Base):
    def __init__(self, *args, **kwargs):
        print "A"
        super(A, self).__init__(*args, **kwargs)

class B(Base):
    def __init__(self, *args, **kwargs):
        print "B"
        super(B, self).__init__(*args, **kwargs)

class C(A):
    def __init__(self, arg, *args, **kwargs):
        print "C","arg=",arg
        super(C, self).__init__(arg, *args, **kwargs)

class D(B):
    def __init__(self, arg, *args, **kwargs):
        print "D", "arg=",arg
        super(D, self).__init__(arg, *args, **kwargs)

class E(C,D):
    def __init__(self, arg, *args, **kwargs):
        print "E", "arg=",arg
        super(E, self).__init__(arg, *args, **kwargs)

print "MRO:", [x.__name__ for x in E.__mro__]
E(10)

수확량

MRO: ['E', 'C', 'A', 'D', 'B', 'Base', 'object']
E arg= 10
C arg= 10
A
D arg= 10
B

이것이 효과가 있으려면,BaseMRO의 끝이 없는 클래스여야 합니다.

상속이 많을 경우(여기에 해당) 모든 매개 변수를 다음과 같이 전달할 것을 제안합니다.**kwargs,그리고 나서.pop사용 후 바로 사용할 수 있습니다(상위 클래스에 필요하지 않은 경우).

class First(object):
    def __init__(self, *args, **kwargs):
        self.first_arg = kwargs.pop('first_arg')
        super(First, self).__init__(*args, **kwargs)

class Second(First):
    def __init__(self, *args, **kwargs):
        self.second_arg = kwargs.pop('second_arg')
        super(Second, self).__init__(*args, **kwargs)

class Third(Second):
    def __init__(self, *args, **kwargs):
        self.third_arg = kwargs.pop('third_arg')
        super(Third, self).__init__(*args, **kwargs)

이것이 그러한 문제들을 해결하는 가장 간단한 방법입니다.

third = Third(first_arg=1, second_arg=2, third_arg=3)

슈퍼로 여겨지는 파이썬의 슈퍼()에서 설명했듯이, 한 가지 방법은 클래스가 필요한 인수를 먹고 나머지를 전달하는 것입니다.따라서, 콜 체인이 도달하면object모든 논쟁은 먹혔고, 그리고.object.__init__인수 없이 호출됩니다(예상대로).따라서 코드는 다음과 같습니다.

class A(object):
    def __init__(self, *args, **kwargs):
        print "A"
        super(A, self).__init__(*args, **kwargs)

class B(object):
    def __init__(self, *args, **kwargs):
        print "B"
        super(B, self).__init__(*args, **kwargs)

class C(A):
    def __init__(self, arg, *args, **kwargs):
        print "C","arg=",arg
        super(C, self).__init__(*args, **kwargs)

class D(B):
    def __init__(self, arg, *args, **kwargs):
        print "D", "arg=",arg
        super(D, self).__init__(*args, **kwargs)

class E(C,D):
    def __init__(self, arg, *args, **kwargs):
        print "E", "arg=",arg
        super(E, self).__init__(*args, **kwargs)

print "MRO:", [x.__name__ for x in E.__mro__]
E(10, 20, 30)

언급URL : https://stackoverflow.com/questions/8972866/correct-way-to-use-super-argument-passing

반응형