在Python中创建简单对象层次结构时,我希望能够从派生类调用父类的方法。在Perl和Java中,这里有一个关键字(
1 2 3 4 5 6 7 8 9 10 11 12 13 | package Foo; sub frotz { return"Bamf"; } package Bar; @ISA = qw(Foo); sub frotz { my $str = SUPER::frotz(); return uc($str); } |
在python中,似乎必须显式地从子类中命名父类。在上面的例子中,我必须执行类似
这似乎是不对的,因为这种行为使得很难创建深度层次结构。如果孩子们需要知道什么类定义了一个继承的方法,那么就会产生各种各样的信息痛苦。
这是python的一个实际限制,是我理解上的一个差距,还是两者都有?
是的,但是只有新式的类。使用
1 2 3 | class Foo(Bar): def baz(self, arg): return super(Foo, self).baz(arg) |
Python也有super:
Return a proxy object that delegates method calls to a parent or sibling class of type.
This is useful for accessing inherited methods that have been overridden in a class.
The search order is same as that used by getattr() except that the type itself is skipped.
例子:
1 2 3 4 5 6 7 8 9 10 | 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() |
1 | ImmediateParentClass.frotz(self) |
无论直接父类定义
Python 3有一个用于调用父方法的不同且更简单的语法。
如果
1 2 3 4 5 | class Foo(Bar): def __init__(self, *args, **kwargs): # invoke Bar.__init__ super().__init__(*args, **kwargs) |
许多答案都解释了如何从父类调用子类中重写的方法。
然而
"how do you call a parent class's method from child class?"
也可以是:
"how do you call inherited methods?"
您可以调用继承自父类的方法,就像它们是子类的方法一样,只要它们没有被覆盖。
例如在python3中:
1 2 3 4 5 6 7 8 9 | 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()的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #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的旧的和新的风格的类,但很常用,例如在构造函数:
1 2 3 4 | class Foo(Bar): def __init__(self): super(Foo, self).__init__() self.baz = 5 |
我建议使用
1 2 3 4 5 6 7 8 9 | 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() |
如果你不知道你可能会得到多少争论,并且想把它们都传递给孩子:
1 2 3 4 | 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中也有一个super()。
说明如何从子类方法调用超类方法的示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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没有任何传递给它的参数。上面的代码在python 3.4版本中是可执行的。
在本例中,cafec_param是基类(父类),abc是子类。abc调用基类中的AWC方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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
在python2中,我使用super()时运气不太好。我用了所以线程如何引用python中的父方法?然后,我添加了我自己的小技巧,我认为这是可用性的改进(特别是如果您有很长的类名)。
在一个模块中定义基类:
1 2 3 4 5 | # myA.py class A(): def foo( self ): print"foo" |
然后将类导入另一个模块
1 2 3 4 5 6 7 | # myB.py from myA import A as parent class B( parent ): def foo( self ): parent.foo( self ) # calls 'A.foo()' |
1 2 3 4 5 6 7 8 9 10 11 12 | 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() |
1 2 3 4 5 6 7 8 9 10 11 | 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() |
这是一个更抽象的方法:
1 | super(self.__class__,self).baz(arg) |