클래스 메서드와 함께 super 사용


83

파이썬에서 super () 함수를 배우려고합니다.

이 예제 (2.6)를 살펴볼 때까지 이해가되었다고 생각하고 제 자신이 갇혀있는 것을 발견했습니다.

http://www.cafepy.com/article/python_attributes_and_methods/python_attributes_and_methods.html#super-with-classmethod-example

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test.py", line 9, in do_something
    do_something = classmethod(do_something)
TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)
>>>

예제 바로 전에이 줄을 읽었을 때 예상했던 것이 아닙니다.

클래스 메서드를 사용하는 경우 super를 호출 할 인스턴스가 없습니다. 다행히도 super는 유형을 두 번째 인수로 사용하더라도 작동합니다. --- 유형은 아래와 같이 super에 직접 전달할 수 있습니다.

do_something ()이 B의 인스턴스와 함께 호출되어야한다고 말함으로써 파이썬이 나에게 말하는 것은 정확히 불가능합니다.


답변:


98

때로는 세부 사항보다는 아이디어의 풍미를 위해 텍스트를 더 많이 읽어야합니다. 이것은 그러한 경우 중 하나입니다.

에서 링크 된 페이지 , 실시 예 2.5, 2.6 및 2.7의 모든 이용해야 하나의 방법 do_your_stuff. (즉, do_something로 변경해야합니다 do_your_stuff.)

로 또한, 네드 Deily 지적 , A.do_your_stuff클래스 메서드이어야한다.

class A(object):
    @classmethod
    def do_your_stuff(cls):
        print 'This is A'

class B(A):
    @classmethod
    def do_your_stuff(cls):
        super(B, cls).do_your_stuff()

B.do_your_stuff()

super(B, cls).do_your_stuff바인딩 된 메서드를 반환합니다 ( 각주 2 참조 ). 이후 cls두 번째 인수로 전달하는 super(), 그것은이다 cls그가 반환 된 방법에 바인딩됩니다. 즉, 클래스 A cls의 메서드 do_your_stuff()에 첫 번째 인수로 전달됩니다 .

반복하려면 super(B, cls).do_your_stuff()원인 Ado_your_stuff와 메서드가 호출되는 cls첫 번째 인수로 전달. 작업에 해당 위해서는, A의는 do_your_stuff클래스 메소드이어야합니다. 링크 된 페이지는 그것을 언급하지 않지만 확실히 그렇습니다.

추신. do_something = classmethod(do_something)classmethod를 만드는 오래된 방법입니다. 새로운 (er) 방법은 @classmethod 데코레이터를 사용하는 것입니다.


참고 super(B, cls)로 교체 할 수 없습니다 super(cls, cls). 그렇게하면 무한 루프가 발생할 수 있습니다. 예를 들면

class A(object):
    @classmethod
    def do_your_stuff(cls):
        print('This is A')

class B(A):
    @classmethod
    def do_your_stuff(cls):
        print('This is B')
        # super(B, cls).do_your_stuff()  # CORRECT
        super(cls, cls).do_your_stuff()  # WRONG

class C(B):
    @classmethod
    def do_your_stuff(cls):
        print('This is C')
        # super(C, cls).do_your_stuff()  # CORRECT
        super(cls, cls).do_your_stuff()  # WRONG

C.do_your_stuff()

올릴 것 RuntimeError: maximum recursion depth exceeded while calling a Python object입니다.

경우 cls입니다 C다음, super(cls, cls)검색 C.mro()후 오는 클래스 C.

In [161]: C.mro()
Out[161]: [__main__.C, __main__.B, __main__.A, object]

클래스이기 때문에 B경우에, cls이다 C, super(cls, cls).do_your_stuff() 항상 호출 B.do_your_stuff. super(cls, cls).do_your_stuff()내부 B.do_your_stuff에서 호출 되기 때문에 B.do_your_stuff무한 루프에서 호출하게 됩니다.

Python3에서는의 0 인수 형식super 이 추가되어 super(B, cls)으로 대체 될 수 있으며 super()Python3은 컨텍스트 super()에서의 정의 class B에서 super(B, cls).

그러나 어떤 상황에서도 super(cls, cls)(또는 비슷한 이유로 super(type(self), self)) 정확하지 않습니다.


super (cls, cls) 사용시 함정이 있습니까?
George Moutsopoulos

2
@GeorgeMoutsopoulos : super(cls, cls)거의 확실히 실수입니다. 이유를 설명하기 위해 위의 게시물을 편집했습니다.
unutbu

38

Python 3에서는에 대한 인수 지정을 건너 뛸 수 있습니다 super.

class A:
    @classmethod
    def f(cls):
        return "A's f was called."

class B(A):
    @classmethod
    def f(cls):
        return super().f()

assert B.f() == "A's f was called."

이 특정 질문이 Python 2를 구체적으로 다루고있는 경우이 답변을 다른 질문으로 이동할 수 있습니다 (연결된 웹 사이트 인 CafePy를 더 이상 사용할 수 없기 때문에 말하기 어렵습니다).
Tankobot 2017

내 프로젝트에서 저에게 효과가 없습니다. 그것은주고있다RuntimeError: super(): no arguments
madtyn

4

좀 더 명확하게하기 위해 기사를 업데이트했습니다 : Python Attributes and Methods # Super

위의 classmethod를 사용하는 예제는 클래스 메소드가 무엇인지 보여줍니다. 인스턴스 대신 클래스 자체를 첫 번째 매개 변수로 전달합니다. 그러나 메소드를 호출하는 데 인스턴스가 필요하지 않습니다. 예를 들면 다음과 같습니다.

>>> class A(object):
...     @classmethod
...     def foo(cls):
...         print cls
... 
>>> A.foo() # note this is called directly on the class
<class '__main__.A'>

2

웹 페이지의 예제는 게시 된대로 작동하는 것 같습니다. do_something슈퍼 클래스에 대한 메서드도 만들었지 만 클래스 메서드로 만들지 않았습니까 ? 다음과 같은 오류가 발생합니다.

>>> class A(object):
...     def do_something(cls):
...         print cls
... #   do_something = classmethod(do_something)
... 
>>> class B(A):
...     def do_something(cls):
...         super(B, cls).do_something()
...     do_something = classmethod(do_something)
... 
>>> B().do_something()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in do_something
TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)

아니요, 내 A 클래스는 다음과 같습니다. class A (object) : def do_your_stuff (self) : print "this is A"게시 할 때 "class A"가 있어야합니까? (do_something = classmethod (do_something))? 문서가 이것에 대해 아무것도 말하지 않은 것 같은데 ..
dza

1
superB do_something 메서드에서 호출의 요점은 수퍼 클래스 중 하나에서 해당 이름의 메서드를 호출하는 것입니다. A (또는 Object)에 하나가 없으면 B (). do_something () 호출이 super object has no attribute do_something. ~ unutbu는 문서의 예제가 잘못되었음을 올바르게 지적합니다.
Ned Deily

0

이 아름다운 사이트와 멋진 커뮤니티 덕분에 이제 요점을 이해했다고 생각합니다.

신경 쓰지 않는다면 내가 수업 방법에 틀렸다면 나를 바로 잡으십시오 (지금 완전히 이해하려고 노력하고 있습니다).


# EXAMPLE #1
>>> class A(object):
...     def foo(cls):
...             print cls
...     foo = classmethod(foo)
... 
>>> a = A()
>>> a.foo()
# THIS IS THE CLASS ITSELF (__class__)
class '__main__.A'

# EXAMPLE #2
# SAME AS ABOVE (With new @decorator)
>>> class A(object):
...     @classmethod
...     def foo(cls):
...             print cls
... 
>>> a = A()
>>> a.foo()
class '__main__.A'

# EXAMPLE #3
>>> class B(object):
...     def foo(self):
...             print self
... 
>>> b = B()
>>> b.foo()
# THIS IS THE INSTANCE WITH ADDRESS (self)
__main__.B object at 0xb747a8ec
>>>

이 그림이 ..


classmethods에 대한 설명이 도움이 될 것입니다. stackoverflow.com/questions/1669445/…
unutbu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.