web-dev-qa-db-ja.com

super()と@staticmethodの相互作用

Super()は静的メソッドで使用するためのものではありませんか?

私が何かをしようとすると

class First(object):
  @staticmethod
  def getlist():
    return ['first']

class Second(First):
  @staticmethod
  def getlist():
    l = super(Second).getlist()
    l.append('second')
    return l

a = Second.getlist()
print a

次のエラーが表示されます

Traceback (most recent call last):
  File "asdf.py", line 13, in <module>
    a = Second.getlist()
  File "asdf.py", line 9, in getlist
    l = super(Second).getlist()
AttributeError: 'super' object has no attribute 'getlist'

Staticmethodsをclassmethodsに変更し、クラスインスタンスをsuper()に渡すと、問題なく動作します。ここで誤ってsuper(type)を呼び出しているのですか、それとも不足しているものがありますか?

48
Ben

短い答え

ここで誤ってsuper(type)を呼び出しているのですか、それとも不足しているものがありますか?

です:はい、あなたはそれを間違って呼び出しています... AND(実際、なぜなら)あなたが見逃しているものがあります.

しかし、気分を害しないでください。これは非常に難しいテーマです。

documentation は、

2番目の引数を省略すると、返されるスーパーオブジェクトはバインドされません。

unboundsuperオブジェクトの使用例は非常に狭く、まれです。 super()に関するディスカッションについては、Michele Simionatoによる次の記事を参照してください。

また、Python 3 here )からバインドされていないsuperを削除することについても強く主張します。

私はあなたがそれを「正しくない」と呼んでいたと述べました(ただし、正確さは文脈なしではほとんど意味がなく、おもちゃの例ではあまり文脈がわかりません)。バインドされていないsuperは非常にまれであり、場合によっては正当化されない可能性があるため、super()を使用する「正しい」方法は、2番目の引数を提供することです。

あなたの場合、あなたの例を機能させる最も簡単な方法は

class First(object):
  @staticmethod
  def getlist():
    return ['first']

class Second(First):
  @staticmethod
  def getlist():
    l = super(Second, Second).getlist()  # note the 2nd argument
    l.append('second')
    return l

a = Second.getlist()
print a

そのように面白いと思うなら、あなたは間違っていません。しかし、ほとんどの人がsuper(X)を見たとき(または自分のコードで試してみるときに期待していること)が期待しているのは、Pythonがあなたにsuper(X, X)

50
John Y

オブジェクトインスタンスで通常のメソッドを呼び出すと、メソッドは最初のパラメーターとしてオブジェクトインスタンスを受け取ります。オブジェクトのクラスとその親クラスを取得できるため、superを呼び出すことは理にかなっています。

オブジェクトインスタンスまたはクラスでclassmethodメソッドを呼び出すと、メソッドはクラスを最初のパラメーターとして受け取ります。親クラスを取得できるため、superを呼び出すことは理にかなっています。

ただし、staticmethodメソッドを呼び出すと、メソッドは何も受け取らず、どのオブジェクトまたはクラスから呼び出されたかを知る方法がありません。これが、静的メソッドでsuperにアクセスできない理由です。

1
Serge Ballesta