program story

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

inputbox 2020. 11. 18. 09:01
반응형

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


파이썬에서 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의 인스턴스로 호출되어야한다고 말함으로써 가능하지 않다는 것입니다.


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

에서 링크 된 페이지 , 실시 예 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)) 정확하지 않습니다.


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 속성 및 방법 # Super

Your example using classmethod above shows what a class method is - it passes the class itself instead of the instance as the first parameter. But you don't even need an instance to call the method, for e.g.:

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

The example from the web page seems to work as published. Did you create a do_something method for the superclass as well but not make it into a classmethod? Something like this will give you that error:

>>> 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)

I think I've understood the point now thanks to this beatiful site and lovely community.

If you don't mind please correct me if I'm wrong on classmethods (which I am now trying to understand fully):


# 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
>>>

I hope this illustration shows ..

참고URL : https://stackoverflow.com/questions/1817183/using-super-with-a-class-method

반응형