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

+507
источник поделиться
15 ответов

Да, но только с классами нового стиля. Используйте функцию 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)
+605
источник

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()
+127
источник
другие ответы

Связанные вопросы


Похожие вопросы

ImmediateParentClass.frotz(self)

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

+78
источник

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

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

class Foo(Bar):

    def __init__(self, *args, **kwargs):
        # invoke Bar.__init__
        super().__init__(*args, **kwargs)
+65
источник

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

Однако

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

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

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

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

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

+35
источник

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

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

class Foo(Bar):
    def __init__(self):
        super(Foo, self).__init__()
        self.baz = 5
+13
источник

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

+6
источник

Существует также супер() в 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.

+4
источник

В 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()'
+1
источник

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

+1
источник
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()
0
источник
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()
-3
источник

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

super(self.__class__,self).baz(arg)
-22
источник

Посмотрите другие вопросы по меткам или Задайте вопрос