Вызов метода родительского класса из дочернего класса в 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, пробелом в моем понимании или обоими?

13 ответов


да, но только с новый-стиль-классы. Используйте super() функция:

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

ImmediateParentClass.frotz(self)

будет просто отлично, будет ли определен непосредственный родительский класс frotz сам или унаследовал его. super нужен только для правильной поддержки несколько наследование (и то он работает только если каждый класс использует его правильно). В общем, AnyClass.whatever собирается искать whatever на AnyClass'предки, если AnyClass не определяет / переопределяет его, и это справедливо для "дочернего класса, вызывающего метод родителя", как и для любого другого случая!


в Python 3 есть другой и более простой синтаксис для вызова родительского метода. Если Foo класс наследует от Bar, затем из Bar.__init__ можно вызвать из Foo С помощью super().__init__():

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

пример использования 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 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.

I найдено: https://docs.python.org/3/tutorial/classes.html#inheritance чтобы быть полезным в понимании того, как вы получаете доступ к унаследованным методам.


в Python тоже есть super (). Это немного шатко, из - за классов старого и нового стиля Python, но довольно часто используется, например, в конструкторах:

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

Я бы рекомендовал использовать CLASS.__bases__ что-то вроде этого!--3-->

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)

(From:Python-самый чистый способ переопределить __init__, где после вызова super() должен использоваться дополнительный кварг?)


в 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.


в Python 2 мне не очень повезло с super (). Я использовал ответ из 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()'

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)