super (인수 전달)를 사용하는 올바른 방법
그래서 저는 Python의 Super Concerned Harmful 을 따르고 그의 예제를 테스트했습니다.
그러나 다른 인수를 예상 하는 메서드를 처리 할 때 올바른 호출 방법을 보여주는 Example 1-3 은 flat-out이 작동하지 않습니다.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
.
자, 분명히 Mr. Knight는 그의 예제가 작동하기를 기대했습니다. 그렇다면 이것이 최신 버전의 Python에서 변경된 것입니까? 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
이것이 작동 Base
하려면 MRO에서 두 번째 클래스 여야합니다.
많은 상속 을 받으려면 ( 여기에서 그렇습니다)를 사용하여 모든 매개 변수를 전달한 **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)
As explained in Python's super() considered super, one way is to have class eat the arguments it requires, and pass the rest on. Thus, when the call-chain reaches object
, all arguments have been eaten, and object.__init__
will be called without arguments (as it expects). So your code should look like this:
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
'Nice programing' 카테고리의 다른 글
MySQL 대 SQL Server 대 Oracle (0) | 2020.10.12 |
---|---|
일부 속성 값이있는 노드를 선택하는 XPath는 다른 노드의 속성 값과 동일합니다. (0) | 2020.10.12 |
JSR이란 무엇이며 그 용도는 무엇입니까? (0) | 2020.10.12 |
모나드가 컴포지션에서 닫히지 않음을 보여주는 구체적인 예 (증거 포함)? (0) | 2020.10.12 |
jQuery 라이브러리에서 사용되는 디자인 패턴 (0) | 2020.10.12 |