如何从Python中的子类调用父类的方法?

在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的实际限制,我的理解差距还是两者兼而有之?

842466 次浏览

使用super()函数:

class Foo(Bar):
def baz(self, **kwargs):
return super().baz(**kwargs)

对于Python<3,您必须明确选择使用新式课堂并使用:

class Foo(Bar):
def baz(self, arg):
return super(Foo, self).baz(arg)

Python也有超级

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()

Python中也有一个Super()。由于Python的旧样式和新式类,它有点不稳定,但在构造函数中非常常用:

class Foo(Bar):
def __init__(self):
super(Foo, self).__init__()
self.baz = 5
ImmediateParentClass.frotz(self)

super仅在正确支持多个继承时才需要(并且只有在每个类都正确使用它时才有效)。一般来说,如果AnyClass没有定义/覆盖whateverAnyClass.whatever将在AnyClass的祖先中查找whatever,这适用于“子类调用父类的方法”以及任何其他情况!

这是一个更抽象的方法:

super(self.__class__,self).baz(arg)

我建议使用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()

以下是使用超级()的示例:

#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()。

如何从子类方法调用超类方法的示例

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())

此示例与上面解释的示例类似。但是有一个区别,超级没有任何参数传递给它。上面的代码在python 3.4版本中可执行。

如果你不知道你可能会得到多少参数,并想把它们都传递给孩子:

class Foo(bar)
def baz(self, arg, *args, **kwargs):
# ... Do your thing
return super(Foo, self).baz(arg, *args, **kwargs)

(来自:Python-覆盖__init__的最干净的方法,其中一个可选的kwarg必须使用后,超级()调用?

python3有一个不同的、更简单的语法来调用父方法。

如果Foo类继承自Bar,那么Bar.__init__可以通过super().__init__()Foo调用:

class Foo(Bar):


def __init__(self, *args, **kwargs):
# invoke Bar.__init__
super().__init__(*args, **kwargs)

在Python 2中,我没有太多的超级()运气。我使用了来自 jimifiki在这个SO线程如何在python中引用父方法?上。 然后,我添加了自己的小转折,我认为这是可用性的改进(特别是如果你有很长的类名)。

在一个模块中定义基类:

 # 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()'

许多答案已经解释了如何从父级调用已在子级中重写的方法。

然而

"如何从子类调用父类的方法?"

也可以只是意味着:

“你怎么称呼继承的方法?”

您可以调用从父类继承的方法,就好像它们是子类的方法一样,只要它们没有被覆盖。

例如在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 对于理解如何访问继承的方法很有用。

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()

在此示例中,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.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