在 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, **kwargs):
return super().baz(**kwargs)
对于 Python < 3,您必须明确选择使用 new-style classes 并使用:
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()
super()
的参数是 Python2 的工件 - 请参阅 Adam 的 Python 3 版本以获得更简洁的代码示例(在 Python3 中,所有类现在都是新式类,所以不需要显式地从 object
继承,并且 super()
不需要类和 self
参数,它只是 super()
)。
ImmediateParentClass.frotz(self)
会很好,无论是直接父类定义 frotz
本身还是继承它。 super
仅在正确支持 multiple 继承时才需要(然后它只有在每个类都正确使用它时才有效)。通常,如果 AnyClass
未定义/覆盖 AnyClass
的祖先,AnyClass.whatever
将在 AnyClass
的祖先中查找 whatever
,这适用于“子类调用父类的方法”以及任何其他事件!
parent
,它在整个类的范围内,不是吗?
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 有助于理解如何访问继承的方法。
self.string
不会做任何事情。但是,在 C 类中,您仍然可以调用 B().bar(string)
下面是一个使用 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)
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 没有任何参数传递给它。上面的代码在 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 线程 how to refer to a parent method in python? 上使用了来自 jimifiki 的答案。然后,我添加了我自己的小改动,我认为这是对可用性的改进(特别是如果你有很长的类名)。
在一个模块中定义基类:
# 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 A(object):
而不是 class A():
然后 super() 将起作用
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.method
。如果您的继承相对干净,这也适用于子类的实例:
class Foo:
def __init__(self, var):
self.var = var
def baz(self):
return self.var
class Bar(Foo):
pass
bar = Bar(1)
assert Foo.baz(bar) == 1
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)
super(self.__class__, self).baz(arg)
。
不定期副业成功案例分享
super(Foo, self)
适用于 Python 2.x 是否正确?在 Python 3.x 中,super()
是首选,对吗?