92

Pythonで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は2番目の引数として型を使用しても機能します。---以下に示すように、タイプを直接superに渡すことができます。

これは、Pythonがdo_something()をBのインスタンスで呼び出す必要があると言っても不可能だと言っていることです。

4

5 に答える 5

112

詳細ではなく、アイデアの趣味のためにテキストをもっと読まなければならない場合があります。これはそのようなケースの1つです。

リンク先のページでは、例2.5、2.6、および2.7はすべて1つの方法を使用する必要がありますdo_your_stuff。(つまり、do_somethingに変更する必要がありますdo_your_stuff。)

さらに、Ned 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に2番目の引数として渡されたため super()cls返されたメソッドにバインドされます。つまり、クラスAclsのメソッドの最初の引数として渡されます。do_your_stuff()

繰り返しますsuper(B, cls).do_your_stuff()が、最初の引数としてpassedを使用してAdo_your_stuffメソッドが呼び出されます。clsそれが機能するためには、A's do_your_stuffはクラスメソッドでなければなりません。リンク先のページにはそのことは記載されていませんが、間違いなくそうです。

PS。do_something = classmethod(do_something)クラスメソッドを作成する古い方法です。新しい(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検索します。Csuper(cls, cls)C.mro()C

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

そのクラスはであるため、がBの場合、常に。を呼び出します。は内部で呼び出されるため、無限ループで呼び出すことになります。clsCsuper(cls, cls).do_your_stuff() B.do_your_stuffsuper(cls, cls).do_your_stuff()B.do_your_stuffB.do_your_stuff

Python3では、の0引数形式superが追加されたため、super(B, cls)で置き換えることができますsuper()。Python3は、コンテキストからsuper()、の定義では。class Bと同等である必要があることを認識しsuper(B, cls)ます。

しかし、いかなる状況においてもsuper(cls, cls)(または同様の理由でsuper(type(self), self))正しいことはありません。

于 2009-11-30T04:22:56.930 に答える
50

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."
于 2017-11-12T08:57:08.993 に答える
4

記事を少し明確にするために更新しました:Pythonの属性とメソッド#スーパー

上記のclassmethodを使用した例は、クラスメソッドが何であるかを示しています。最初のパラメーターとしてインスタンスではなくクラス自体を渡します。ただし、メソッドを呼び出すためのインスタンスも必要ありません。たとえば、次のようになります。

>>> class A(object):
...     @classmethod
...     def foo(cls):
...         print cls
... 
>>> A.foo() # note this is called directly on the class
<class '__main__.A'>
于 2009-12-03T06:11:25.337 に答える
2

Webページの例は、公開されたとおりに機能しているようです。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)
于 2009-11-30T00:10:37.617 に答える
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
>>>

このイラストが..を示していることを願っています。

于 2009-11-30T17:01:05.287 に答える