Pythonで子クラスから親クラスのメソッドを呼び出しますか?
-
03-07-2019 - |
質問
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 3.xでは、次を使用できます。
class Foo(Bar):
def baz(self, arg):
return super().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 継承を適切にサポートするためにのみ必要です(すべてのクラスが適切に使用する場合にのみ機能します)。一般に、 AnyClass
がそうでない場合、 AnyClass.whatever
は AnyClass
の祖先で whatever
を検索します。定義/オーバーライドします。これは、「子クラスが親のメソッドを呼び出す」場合にも当てはまります。他の発生については!
Python 3 には、親メソッドを呼び出すための異なるシンプルな構文があります。
Foo
クラスが Bar
から継承する場合、 Bar .__ init __
から Foo
から< code> super().__ init __():
class Foo(Bar):
def __init__(self, *args, **kwargs):
# invoke Bar.__init__
super().__init__(*args, **kwargs)
多くの回答が、子でオーバーライドされた親からメソッドを呼び出す方法を説明しています。
ただし
&quot;子クラスから親クラスのメソッドを呼び出す方法&quot;
次の意味もあります:
&quot;継承されたメソッドをどのように呼び出すのですか?&quot;
上書きされていない限り、子クラスのメソッドであるかのように、親クラスから継承されたメソッドを呼び出すことができます。
e.g。 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 バージョンで実行可能です。
Python 2では、super()であまり運がありませんでした。からの回答を使用しました このSOスレッドのjimifiki pythonで親メソッドを参照する方法。 それから、私はそれ自身にちょっとしたひねりを加えました。それはユーザビリティの改善だと思います(特に長いクラス名を持っている場合)。
1つのモジュールで基本クラスを定義します:
# myA.py
class A():
def foo( self ):
print "foo"
次に、クラスを別のモジュールに親として
インポートします:
# myB.py
from myA import A as parent
class B( parent ):
def foo( self ):
parent.foo( self ) # calls 'A.foo()'
では、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
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()
class a(object):
def my_hello(self):
print "hello ravi"
class b(a):
def my_hello(self):
super(b,self).my_hello()
print "hi"
obj = b()
obj.my_hello()
これはより抽象的なメソッドです:
super(self.__class__,self).baz(arg)