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の実際の制限、私の理解のギャップ、あるいはその両方でしょうか。
はい、ただし 新しいスタイルのクラスでのみ 。 super()
関数を使用します。
class Foo(Bar):
def baz(self, arg):
return super(Foo, self).baz(arg)
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()
ImmediateParentClass.frotz(self)
直接の親クラスがfrotz
自身を定義しているか継承しているかに関わらず、問題ありません。 super
は multiple inheritanceの適切なサポートのためにのみ必要です(そしてそれはすべてのクラスがそれを適切に使用する場合にのみ機能します)。一般的に、whatever
がそれを定義したり上書きしたりしない場合、AnyClass.whatever
はAnyClass
の祖先でAnyClass
を検索しようとします、そしてこれは他の場合と同様に "子クラス呼び出し親のメソッド"にも当てはまります!
Python 3 には、親メソッドを呼び出すための異なるより単純な構文があります。
Foo
クラスがBar
を継承している場合は、super().__init__()
を介してFoo
からBar.__init__
から呼び出すことができます。
class Foo(Bar):
def __init__(self, *args, **kwargs):
# invoke Bar.__init__
super().__init__(*args, **kwargs)
多くの回答が、子でオーバーライドされている親からメソッドを呼び出す方法を説明しています。
しかしながら
「どのように子クラスから親クラスのメソッドを呼び出すのですか?」
また単に意味することができます:
「継承されたメソッドをどのように呼び出しますか?」
上書きされていない限り、親クラスから継承したメソッドを子クラスのメソッドであるかのように呼び出すことができます。
例えば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 継承されたメソッドにアクセスする方法を理解するのに役立ちます。
これが 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
Pythonにもsuper()があります。 Pythonの新旧のクラスのせいで、少々不思議ですが、かなり一般的に使われています。コンストラクタでは:
class Foo(Bar):
def __init__(self):
super(Foo, self).__init__()
self.baz = 5
私は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()
引数がいくつあるかわからない場合は、それらすべてを子に渡したい場合もあります。
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__をオーバーライドする最もクリーンな方法? )
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バージョンで実行可能です。
この例では、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
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()'
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()