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

StackOverflow https://stackoverflow.com/questions/805066

Вопрос

При создании простой иерархии объектов в 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, пробелом в моем понимании или и тем, и другим?

Это было полезно?

Решение

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

Другие советы

Python также имеет супер также:

супер(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, *args, **kwargs):
        # invoke Bar.__init__
        super().__init__(*args, **kwargs)

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

Однако

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

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

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

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

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

Вот пример использования супер():

#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 тоже есть функция super().Это немного неудобно из-за классов старого и нового стилей Python, но довольно часто используется, напримерв конструкторах:

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

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

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

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

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

В 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 в этой теме 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()'

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

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 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)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top