web-dev-qa-db-ja.com

Pythonで子クラスから親クラスのメソッドを呼び出す?

Pythonで単純なオブジェクト階層を作成するとき、派生クラスから親クラスのメソッドを呼び出せるようにしたいです。 PerlとJavaでは、これに対するキーワードがあります( super )。 Perlでは、私はこれをするかもしれません:

package Foo;

sub frotz {
    return "Bamf";
}

package Bar;
@ISA = qw(Foo);

sub frotz {
   my $str = SUPER::frotz();
   return uc($str);
}

Pythonでは、子から親クラスに明示的に名前を付ける必要があるようです。上の例では、Foo::frotz()のようなことをしなければなりません。

この振る舞いは深い階層を作るのを難しくするので、これは正しくないようです。どのクラスが継承されたメソッドを定義しているのかを子供が知る必要がある場合は、あらゆる種類の情報が生成されます。

これはpythonの実際の制限、私の理解のギャップ、あるいはその両方でしょうか。

496
jjohn

はい、ただし 新しいスタイルのクラスでのみsuper() 関数を使用します。

class Foo(Bar):
    def baz(self, arg):
        return super(Foo, self).baz(arg)
592
Adam Rosenfield

Pythonには super もあります。

super(type[, object-or-type])

メソッド呼び出しをタイプの親クラスまたは兄弟クラスに委任するプロキシオブジェクトを返します。これは、クラス内でオーバーライドされた継承メソッドにアクセスするのに役立ちます。検索順序は、型自体がスキップされることを除いて、getattr()によって使用されるものと同じです。

例:

class A(object):     # deriving from 'object' declares A as a 'new-style-class'
    def foo(self):
        print "foo"

class B(A):
    def foo(self):
        super(B, self).foo()   # calls 'A.foo()'

myB = B()
myB.foo()
125
Jay
ImmediateParentClass.frotz(self)

直接の親クラスがfrotz自身を定義しているか継承しているかに関わらず、問題ありません。 super multiple inheritanceの適切なサポートのためにのみ必要です(そしてそれはすべてのクラスがそれを適切に使用する場合にのみ機能します)。一般的に、whateverがそれを定義したり上書きしたりしない場合、AnyClass.whateverAnyClassの祖先でAnyClassを検索しようとします、そしてこれは他の場合と同様に "子クラス呼び出し親のメソッド"にも当てはまります!

78
Alex Martelli

Python 3 には、親メソッドを呼び出すための異なるより単純な構文があります。

FooクラスがBarを継承している場合は、super().__init__()を介してFooからBar.__init__から呼び出すことができます。

class Foo(Bar):

    def __init__(self, *args, **kwargs):
        # invoke Bar.__init__
        super().__init__(*args, **kwargs)
62
Arun Ghosh

多くの回答が、子でオーバーライドされている親からメソッドを呼び出す方法を説明しています。

しかしながら

「どのように子クラスから親クラスのメソッドを呼び出すのですか?」

また単に意味することができます:

「継承されたメソッドをどのように呼び出しますか?」

上書きされていない限り、親クラスから継承したメソッドを子クラスのメソッドであるかのように呼び出すことができます。

例えばPython 3では:

class A():
  def bar(self, string):
    print("Hi, I'm bar, inherited from A"+string)

class B(A):
  def baz(self):
    self.bar(" - called by baz in B")

B().baz() # prints out "Hi, I'm bar, inherited from A - called by baz in B"

はい、これはかなり明白かもしれませんが、私はこれを指摘せずに人々があなたがpythonで継承されたメソッドにアクセスするためだけにばかげたフープを飛び越えなければならないという印象でこのスレッドを残すかもしれません特に、この質問が「Pythonで親クラスのメソッドにアクセスする方法」の検索で高い評価を得ているため、OPはpythonを初めて使う人の視点から書かれています。

https://docs.python.org/3/tutorial/classes.html#inheritance 継承されたメソッドにアクセスする方法を理解するのに役立ちます。

33
Ben

これが super() の使用例です。

#New-style classes inherit from object, or from another new-style class
class Dog(object):

    name = ''
    moves = []

    def __init__(self, name):
        self.name = name

    def moves_setup(self):
        self.moves.append('walk')
        self.moves.append('run')

    def get_moves(self):
        return self.moves

class Superdog(Dog):

    #Let's try to append new fly ability to our Superdog
    def moves_setup(self):
        #Set default moves by calling method of parent class
        super(Superdog, self).moves_setup()
        self.moves.append('fly')

dog = Superdog('Freddy')
print dog.name # Freddy
dog.moves_setup()
print dog.get_moves() # ['walk', 'run', 'fly']. 
#As you can see our Superdog has all moves defined in the base Dog class
26
yesnik

Pythonにもsuper()があります。 Pythonの新旧のクラスのせいで、少々不思議ですが、かなり一般的に使われています。コンストラクタでは:

class Foo(Bar):
    def __init__(self):
        super(Foo, self).__init__()
        self.baz = 5
13
lawrence

私はCLASS.__bases__のようなものを使うことをお勧めします

class A:
   def __init__(self):
        print "I am Class %s"%self.__class__.__name__
        for parentClass in self.__class__.__bases__:
              print "   I am inherited from:",parentClass.__name__
              #parentClass.foo(self) <- call parents function with self as first param
class B(A):pass
class C(B):pass
a,b,c = A(),B(),C()
9
Joran Beasley

引数がいくつあるかわからない場合は、それらすべてを子に渡したい場合もあります。

class Foo(bar)
    def baz(self, arg, *args, **kwargs):
        # ... Do your thing
        return super(Foo, self).baz(arg, *args, **kwargs)

(From: Python - super()呼び出しの後にオプションのkwargを使用する必要がある__init__をオーバーライドする最もクリーンな方法?

6
Robin Winslow

Pythonにもsuper()があります。

スーパークラスメソッドがサブクラスメソッドから呼び出される方法の例

class Dog(object):
    name = ''
    moves = []

    def __init__(self, name):
        self.name = name

    def moves_setup(self,x):
        self.moves.append('walk')
        self.moves.append('run')
        self.moves.append(x)
    def get_moves(self):
        return self.moves

class Superdog(Dog):

    #Let's try to append new fly ability to our Superdog
    def moves_setup(self):
        #Set default moves by calling method of parent class
        super().moves_setup("hello world")
        self.moves.append('fly')
dog = Superdog('Freddy')
print (dog.name)
dog.moves_setup()
print (dog.get_moves()) 

この例は、上で説明したものと似ています。ただし、superに引数が渡されないという違いが1つあります。上記のコードは、Python 3.4バージョンで実行可能です。

4
kkk

この例では、cafec_paramは基本クラス(親クラス)で、abcは子クラスです。 abcは基本クラスのAWCメソッドを呼び出します。

class cafec_param:

    def __init__(self,precip,pe,awc,nmonths):

        self.precip = precip
        self.pe = pe
        self.awc = awc
        self.nmonths = nmonths

    def AWC(self):

        if self.awc<254:
            Ss = self.awc
            Su = 0
            self.Ss=Ss
        else:
            Ss = 254; Su = self.awc-254
            self.Ss=Ss + Su   
        AWC = Ss + Su
        return self.Ss
         

    def test(self):
        return self.Ss
        #return self.Ss*4

class abc(cafec_param):
    def rr(self):
        return self.AWC()


ee=cafec_param('re',34,56,2)
dd=abc('re',34,56,2)
print(dd.rr())
print(ee.AWC())
print(ee.test())

出力

56

56

56

1
Khan

Python 2では、私はsuper()であまり運がありませんでした。私はこのSO thread pythonで親メソッドを参照する方法? についてjimifikiの回答を使用しました。それから私はそれに私自身のちょっとした工夫を加えました、それは私が使いやすさにおける改善であると思います(あなたが長いクラス名を持っているなら特に)。

1つのモジュールで基本クラスを定義します。

 # myA.py

class A():     
    def foo( self ):
        print "foo"

それからそのクラスを他のモジュールas parentにインポートします。

# myB.py

from myA import A as parent

class B( parent ):
    def foo( self ):
        parent.foo( self )   # calls 'A.foo()'
1
BuvinJ
class department:
    campus_name="attock"
    def printer(self):
        print(self.campus_name)

class CS_dept(department):
    def overr_CS(self):
        department.printer(self)
        print("i am child class1")

c=CS_dept()
c.overr_CS()
0
maryam mehboob