从子类调用父类的方法?

问题:从子类调用父类的方法?

在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中的实际限制,我的理解上的空白还是两者都有?

When creating a simple object hierarchy in Python, I’d like to be able to invoke methods of the parent class from a derived class. In Perl and Java, there is a keyword for this (super). In Perl, I might do this:

package Foo;

sub frotz {
    return "Bamf";
}

package Bar;
@ISA = qw(Foo);

sub frotz {
   my $str = SUPER::frotz();
   return uc($str);
}

In Python, it appears that I have to name the parent class explicitly from the child. In the example above, I’d have to do something like Foo::frotz().

This doesn’t seem right since this behavior makes it hard to make deep hierarchies. If children need to know what class defined an inherited method, then all sorts of information pain is created.

Is this an actual limitation in python, a gap in my understanding or both?


回答 0

是的,但仅适用于新型类。使用super()功能:

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

对于python <3,请使用:

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

Yes, but only with new-style classes. Use the super() function:

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

For python < 3, use:

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

回答 1

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 also has super as well:

super(type[, object-or-type])

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.

Example:

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

回答 2

ImmediateParentClass.frotz(self)

无论直接父类定义frotz自己还是继承它,都将很好。 super仅在正确支持多重继承时才需要(只有在每个类都正确使用它的情况下才起作用)。通常,如果未定义或覆盖它,AnyClass.whateverwhateverAnyClasss的祖先中查找AnyClass,这对于“调用父方法的子类”以及其他任何情况都适用!

ImmediateParentClass.frotz(self)

will be just fine, whether the immediate parent class defined frotz itself or inherited it. super is only needed for proper support of multiple inheritance (and then it only works if every class uses it properly). In general, AnyClass.whatever is going to look up whatever in AnyClass‘s ancestors if AnyClass doesn’t define/override it, and this holds true for “child class calling parent’s method” as for any other occurrence!


回答 3

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

如果Foo类继承Bar,然后Bar.__init__可以从调用Foo通过super().__init__()

class Foo(Bar):

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

Python 3 has a different and simpler syntax for calling parent method.

If Foo class inherits from Bar, then from Bar.__init__ can be invoked from Foo via super().__init__():

class Foo(Bar):

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

回答 4

许多答案已经解释了如何从父级中调用已被子级覆盖的方法。

然而

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

也可能意味着:

“您如何称呼继承的方法?”

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

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

Many answers have explained how to call a method from the parent which has been overridden in the child.

However

“how do you call a parent class’s method from child class?”

could also just mean:

“how do you call inherited methods?”

You can call methods inherited from a parent class just as if they were methods of the child class, as long as they haven’t been overwritten.

e.g. in 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"

yes, this may be fairly obvious, but I feel that without pointing this out people may leave this thread with the impression you have to jump through ridiculous hoops just to access inherited methods in python. Especially as this question rates highly in searches for “how to access a parent class’s method in Python”, and the OP is written from the perspective of someone new to python.

I found: https://docs.python.org/3/tutorial/classes.html#inheritance to be useful in understanding how you access inherited methods.


回答 5

这是使用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

Here is an example of using 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

回答 6

Python中也有一个super()。由于Python的旧类和新类,这有点奇怪,但是在构造函数中非常常用:

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

There’s a super() in Python too. It’s a bit wonky, because of Python’s old- and new-style classes, but is quite commonly used e.g. in constructors:

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

回答 7

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

I would recommend using CLASS.__bases__ something like this

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

回答 8

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

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

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

If you don’t know how many arguments you might get, and want to pass them all through to the child as well:

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

(From: Python – Cleanest way to override __init__ where an optional kwarg must be used after the super() call?)


回答 9

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

There is a super() in python also.

Example for how a super class method is called from a sub class method

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

This example is similar to the one explained above.However there is one difference that super doesn’t have any arguments passed to it.This above code is executable in python 3.4 version.


回答 10

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

In this example cafec_param is a base class (parent class) and abc is a child class. abc calls the AWC method in the base class.

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

回答 11

在Python 2中,我对super()不太满意。我在这个SO线程上使用了jimifiki的答案,如何在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()'

In Python 2, I didn’t have a lot luck with super(). I used the answer from jimifiki on this SO thread how to refer to a parent method in python?. Then, I added my own little twist to it, which I think is an improvement in usability (Especially if you have long class names).

Define the base class in one module:

 # myA.py

class A():     
    def foo( self ):
        print "foo"

Then import the class into another modules as parent:

# myB.py

from myA import A as parent

class B( parent ):
    def foo( self ):
        parent.foo( self )   # calls 'A.foo()'

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

回答 13

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

回答 14

这是一个更抽象的方法:

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

This is a more abstract method:

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