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