从Python中的子类调用父类的方法?
在Python中创build简单的对象层次结构时,我希望能够从派生类中调用父类的方法。 在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()。
这看起来不正确,因为这种行为使得很难做出深层次的结构。 如果孩子需要知道什么类定义了一个inheritance的方法,那么就会产生各种信息的痛苦。
这是python的一个实际的限制,在我的理解或两者的差距?
是的,但只有新式的课程 。 使用super()
函数:
class Foo(Bar): def baz(self, arg): return super(Foo, self).baz(arg)
Python也有很好的function:
super (type[, object-or-type])
返回一个将方法调用委托给父类或兄弟类的代理对象。 这对访问在类中被覆盖的inheritance方法很有用。 search顺序与getattr()使用的顺序相同,只是跳过了types本身。
例:
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
本身或inheritance它。 super
只是为了适当的支持多重inheritance(然后它只适用于每个类都正确使用它)。 一般来说,如果AnyClass
没有定义/覆盖AnyClass
, AnyClass.whatever
将会在AnyClass
的祖先中查找whatever
,对于任何其他情况,“子类调用父方法”也是如此。
这是一个使用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 3具有不同且更简单的语法。 如果Foo
类inheritance自Bar
,那么从Bar.__init__
可以使用super().__init__()
从Foo
调用:
class Foo(Bar): def __init__(self): super().__init__()
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()
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没有任何parameter passing给它。上面的代码在Python 3.4版本中是可执行的。
许多答案已经解释了如何从父母中调用一个已被孩子覆盖的方法。
然而
“你怎么从小孩class级调用父class的方法?”
也可能只是意味着:
“你怎么称之为inheritance的方法?”
您可以调用从父类inheritance的方法,就像它们是子类的方法一样,只要它们没有被覆盖。
例如在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中的inheritance方法。 特别是当这个问题在search“如何在Python中访问一个父类的方法”时高度评价,而OP是从一个新的pythonangular度编写的。
我发现: https : //docs.python.org/3/tutorial/classes.html#inheritance在理解如何访问inheritance的方法方面很有用。
如果你不知道你可能得到多less论点,并想把它们全部传给孩子:
class Foo(bar) def baz(self, arg, *args, **kwargs): # ... Do your thing return super(Foo, self).baz(arg, *args, **kwargs)
(来自: Python – 最好的方法来覆盖__init__在super()调用后必须使用可选的kwarg? )
在Python 2中,我没有运用super()。 我用这个SO线程从jimifiki的答案如何引用在Python中的父方法? 。 然后,我添加了自己的小小的转折,我认为这是对可用性的改进(特别是如果你有很长的类名)。
在一个模块中定义基类:
# myA.py class A(): def foo( self ): print "foo"
然后将该类as parent
类导入到另一个模块as parent
:
# myB.py from myA import A as parent class B( parent ): def foo( self ): parent.foo( self ) # calls 'A.foo()'
这是一个更抽象的方法:
super(self.__class__,self).baz(arg)