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

Ответ 1

Да, но только с классами нового стиля. Используйте функцию super():

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

Для Python 3.x вы можете использовать:

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

Ответ 2

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

Ответ 3

ImmediateParentClass.frotz(self)

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

Ответ 4

Python 3 имеет другой и более простой синтаксис для вызова родительского метода.

Если класс Foo наследуется от Bar, то из Bar.__init__ можно вызвать из Foo через super().__init__():

class Foo(Bar):

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

Ответ 5

Многие ответы объяснили, как вызвать метод из родителя, который был переопределен в дочернем.

Однако

"как вы вызываете метод родительского класса из дочернего класса?"

может также означать:

"как вы называете унаследованные методы?"

Вы можете вызывать методы, унаследованные от родительского класса, точно так же, как если бы они были методами дочернего класса, если они не были перезаписаны.

например. в 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 чтобы помочь вам понять, как вы получаете доступ к унаследованным методам.

Ответ 6

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

Ответ 7

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

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

Ответ 8

Я бы рекомендовал использовать 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()

Ответ 9

Если вы не знаете, сколько аргументов вы можете получить, и хотите передать их всем ребенку:

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

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

Ответ 10

Существует также супер() в python.

Пример того, как метод суперкласса вызывается из метода подкласса

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

Ответ 11

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

Ответ 12

в этом примере 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())

Ответ 13

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

Ответ 14

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

Ответ 15

Это более абстрактный метод:

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