2011-02-03 14 views
8

サブクラスのメソッドをオーバーライドするとき、私は頻繁にこの操作を行います。スーパーのショートカット(タイプ(自己)、自己)

def method_x(self): 
    x = super(type(self), self).method_x() 

    [Some extra code] 
    return x 

私の質問は:スーパーのための近道はあります(タイプ(自己) 、自己)?

+14

これを読んでいる人には警告:上記のコードは*間違っています。それを模倣しないでください! –

+0

Glenn、Duncan:これが間違っていることを指摘してくれてありがとう。私はコードをgrepしてこれを変更する必要があります。 –

+0

@グレンメイナード:なぜあなたはそれを間違ったものと考えるのか分かりません。 'super(self .__ class__、self)'を使うのは良いでしょうか? – martineau

答えて

17

Do not do:もしsuperが最初の引数としてtype(self)を使うことができれば、まず最初に2つの引数を取るように書かれていないでしょう。実際のクラスは、クラスがサブクラス化されていれば変更可能な式ではなく、ここで渡す必要があります。

スーパーの最初の引数は、現在のメソッド定義を含むクラスである必要があります。これは、検索を開始するベースのリストのどこにスーパーを伝えているかにあります。

super()これは魔法のようにコンパイル時に扱われますが、Python 2.xでは単なる普通の関数なので、それ自体のためのパラメータを見つける方法はありません。

[私の最初のポイントに追加する編集] 実際には、Pythonの2.xではsuper()を使用する別のあまり使用方法がありますあなたはスーパーの結合していないフォームを使用して、あなたがそれにアクセスするとき、それはバインド持つことができます。

>>> class A(object): 
    def foo(self): 
     print "A.foo" 


>>> class B(A): 
    def foo(self): 
     self.__super.foo() 
     print "B.foo" 


>>> B._B__super = super(B) 
>>> class C(A): 
    def foo(self): 
     self.__super.foo() 
     print "C.foo" 


>>> C._C__super = super(C) 
>>> class D(C,B): pass 

>>> D._D__super = super(D) 
>>> D().foo() 
A.foo 
B.foo 
C.foo 

ここで重要な漁獲があります:あなたは、各superオブジェクトを格納するために別の名前を使用する必要があり、あなたが使用して行うことができますself.__superですが、クラス定義に直接バインドされていないsuperを作成することはできません(まだ存在しない場合はクラスに名前を付けることができないため)。また、外部に作成する場合は、手動で名前を難読化して、 __superクラスのオブジェクトです。 Python 2.6以降では、おそらくこれをクラスデコレータとしてまとめることができます。

+1

これを推奨することをお勧めします。それは珍しいことをすることで勝つことはあまりありません。 –

+2

はい、それはおそらくそれがあまり使用されていない理由であるが乱雑ですが、私はオプションとしてそれを言及すべきだと思った。はるかに良いオプションは、Python 3.xを使用することです(必要なライブラリがあればそれをサポートしています) – Duncan

+0

今日python3を使って調べました。私はPylons Pyramidを使用していますが、依存関係のいくつかはpy3をまだサポートしていないので、2,3ヶ月後に確認しなければなりません。 –