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

jjo*_*ohn 553 python inheritance class object

在Python中创建一个简单的对象层次结构时,我希望能够从派生类中调用父类的方法.在Perl和Java中,有一个关键字this(super).在Perl中,我可能会这样做:

package Foo;

sub frotz {
    return "Bamf";
}

package Bar;
@ISA = qw(Foo);

sub frotz {
   my $str = SUPER::frotz();
   return uc($str);
}
Run Code Online (Sandbox Code Playgroud)

在python中,似乎我必须从子级明确命名父类.在上面的例子中,我必须做类似的事情Foo::frotz().

这似乎不对,因为这种行为使得很难制作深层次结构.如果孩子需要知道哪个类定义了一个继承的方法,那么就会产生各种各样的信息痛苦.

这是python中的实际限制,是我理解中的差距还是两者兼而有之?

Ada*_*eld 663

是的,但只适用于新式课程.使用super()功能:

class Foo(Bar):
    def baz(self, arg):
        return super(Foo, self).baz(arg)
Run Code Online (Sandbox Code Playgroud)

  • 你能不能"退回Bar.baz(self,arg)"吗?如果是这样,哪个更好? (51认同)
  • 语法`super(Foo,self)`适用于Python 2.x正确吗?在Python 3.x中,`super()`首选正确吗? (26认同)
  • 是的,你可以,但是OP正在询问如何在没有明确命名调用站点的超类(Bar,在本例中)的情况下执行此操作. (13认同)
  • super()对于多重继承很奇怪.它呼唤"下一个"课程.这可能是父类,或者可能是一些完全不相关的类,它出现在层次结构的其他位置. (7认同)
  • 我使用Python 2.x,当我这样做时,我得到"错误:必须是类型,而不是classobj" (6认同)
  • 史蒂夫,大多数时候它会做最合理的事情,例如在面对 http://en.wikipedia.org/wiki/Diamond_problem 时。 (2认同)
  • @SteveJessop,本文很好地描述了继承的顺序优先级:https://rhettinger.wordpress.com/2011/05/26/super-thinked-super/ (2认同)
  • @nurettin:如果所有基础都使用“super()”,它们也会调用多个基础方法。`Bar.baz` 更明确、更灵活,但它意味着更紧密的耦合;一致使用 super() 可以让您一致地调用方法的所有版本,而无需命名类,也不必冒不调用给定方法或多次调用该方法的风险。 (2认同)

Jay*_*Jay 133

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()
Run Code Online (Sandbox Code Playgroud)

  • 比Adam更好的例子,因为你演示了使用带对象基类的新式类.只是错过了新式课程的链接. (6认同)
  • 仅调用 super().foo() 而不是 super(B, self).foo() 有什么区别吗?两者似乎都在工作。 (2认同)

Ale*_*lli 79

ImmediateParentClass.frotz(self)
Run Code Online (Sandbox Code Playgroud)

无论是直接的父类定义frotz自己还是继承它,都会很好. super仅需要对多重继承的适当支持(然后它只适用于每个类正确使用它).一般情况下,AnyClass.whatever是要查找whateverAnyClass的祖先,如果AnyClass没有定义/覆盖它,而这个'呼吁父母的方法子类’作为任何其它情况适用于真!


Aru*_*osh 71

Python 3具有用于调用父方法的不同且更简单的语法.

如果Foo类继承自Bar,则Bar.__init__可以从Foovia 调用from super().__init__():

class Foo(Bar):

    def __init__(self, *args, **kwargs):
        # invoke Bar.__init__
        super().__init__(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

  • 很高兴听到python 3有一个更好的解决方案.问题来自python 2.X. (还是)感谢你的建议. (5认同)

Ben*_*Ben 38

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

然而

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

也可能只是意味着:

"你怎么称为继承方法?"

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

例如在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"
Run Code Online (Sandbox Code Playgroud)

是的,这可能是相当明显的,但我觉得如果不指出这一点,人们可能会留下这个线程的印象,你必须跳过荒谬的箍只是为了访问python中的继承方法.特别是因为这个问题在"如何在Python中访问父类的方法"的搜索中得到高度评价,而OP是从一个新的python的角度编写的.

我发现:https: //docs.python.org/3/tutorial/classes.html#inheritance 有助于理解如何访问继承的方法.


yes*_*nik 26

以下是使用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
Run Code Online (Sandbox Code Playgroud)


law*_*nce 13

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

class Foo(Bar):
    def __init__(self):
        super(Foo, self).__init__()
        self.baz = 5
Run Code Online (Sandbox Code Playgroud)


Jor*_*ley 9

我建议使用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()
Run Code Online (Sandbox Code Playgroud)

  • 请记住,正如您从这里对 **super** 的引用量中可以看出的那样,人们真的不愿意使用 __bases__ ,除非您正在做一些非常深入的事情。如果您不喜欢**super**,请查看**mro**。获取 **mro** 中的第一个条目比跟踪 __bases__ 中要使用的条目更安全。Python 中的多重继承会向后扫描某些事物,而向前扫描其他事物,因此让语言展开该过程是最安全的。 (2认同)

Rob*_*low 7

如果你不知道你可能得到多少个参数,并且想要将它们全部传递给孩子:

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

(来自:Python - 覆盖__init__的最干净的方法,在super()调用之后必须使用可选的kwarg?)


kkk*_*kkk 5

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()) 
Run Code Online (Sandbox Code Playgroud)

这个例子类似于上面解释的那个。但是有一个区别是 super 没有任何参数传递给它。上面的代码在 python 3.4 版本中是可执行的。


Kha*_*han 5

在这个例子中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())
Run Code Online (Sandbox Code Playgroud)

输出

56

56

56
Run Code Online (Sandbox Code Playgroud)