首页 文章

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

提问于
浏览
451

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

14 回答

  • 5

    在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()'
    
  • 1

    这是一个更抽象的方法:

    super(self.__class__,self).baz(arg)
    
  • -3
    ImmediateParentClass.frotz(self)
    

    无论直接父类是定义 frotz 本身还是继承它,都会没问题 . 只有在适当支持多重继承时才需要 super (然后只有在每个类正确使用它时它才有效) . 一般情况下,如果 AnyClass 没有定义/覆盖它, AnyClass.whatever 将在 AnyClass 的祖先中查找 whatever ,这对于"child class calling parent's method"也适用于任何其他事件!

  • 42

    我建议使用_471915这样的东西

    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()
    
  • 26
    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()
    
  • 74

    是的,但只有new-style classes . 使用super()功能:

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

    Python 3具有用于调用父方法的不同且更简单的语法 . 如果 Foo 类继承自 Bar ,则可以使用 super().__init__()Foo 调用 Bar.__init__

    class Foo(Bar):
        def __init__(self):
            super().__init__()
    
  • 9

    以下是使用 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
    
  • 13

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

    Output

    56

    56

    56

  • 25

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

    然而

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

    也可能只是意味着:

    “你怎么称为继承方法?”

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

    例如在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有助于理解如何访问继承的方法 .

  • 105

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

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

    (来自:Python - Cleanest way to override init where an optional kwarg must be used after the super() call?

  • -21

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

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

    class Foo(Bar):
        def __init__(self):
            super(Foo, self).__init__()
            self.baz = 5
    
  • 547

    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版本中执行 .

相关问题