Использовать & ldquo; функции в классе A & rdquo; в __init__ класса B после наследования [дубликат]

Давайте перепишем ваш код следующим образом:

x = 1
y = [x]
z = y * 4

myList = [z] * 3

После этого запустите следующий код, чтобы сделать все более понятным. Что делает код, в основном печатает id s полученных объектов, которые

Вернуть «идентификатор» объекта

и поможет нам идентифицировать их и проанализировать, что происходит:

print("myList:")
for i, subList in enumerate(myList):
    print("\t[{}]: {}".format(i, id(subList)))
    for j, elem in enumerate(subList):
        print("\t\t[{}]: {}".format(j, id(elem)))

И вы получите следующий результат:

x: 1
y: [1]
z: [1, 1, 1, 1]
myList:
    [0]: 4300763792
        [0]: 4298171528
        [1]: 4298171528
        [2]: 4298171528
        [3]: 4298171528
    [1]: 4300763792
        [0]: 4298171528
        [1]: 4298171528
        [2]: 4298171528
        [3]: 4298171528
    [2]: 4300763792
        [0]: 4298171528
        [1]: 4298171528
        [2]: 4298171528
        [3]: 4298171528

Итак, теперь давайте шаг за шагом. У вас есть x, который является 1, и единственным списком элементов y, содержащим x. Ваш первый шаг - y * 4, который даст вам новый список z, который в основном [x, x, x, x], т. Е. Создает новый список, который будет содержать 4 элемента, которые являются ссылками на исходный объект x. Чистый шаг очень похож. В основном вы делаете z * 3, который является [[x, x, x, x]] * 3 и возвращает [[x, x, x, x], [x, x, x, x], [x, x, x, x]] по той же причине, что и для первого шага.

441
задан jjohn 5 May 2014 в 19:29
поделиться

14 ответов

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

class Foo(Bar):
    def baz(self, arg):
        return super(Foo, self).baz(arg)
508
ответ дан Adam Rosenfield 20 August 2018 в 23:22
поделиться
  • 1
    Можете ли вы также не делать & quot; вернуть Bar.baz (self, arg) & quot ;? Если да, то что было бы лучше? – Chris Cameron 30 April 2009 в 03:09
  • 2
    Да, вы можете, но OP спрашивал, как это сделать, без явного наложения суперкласса на сайт вызова (в этом случае Bar (Bar)). – Adam Rosenfield 30 April 2009 в 03:13
  • 3
    super () является странным с множественным наследованием. Он вызывает «следующий». класс. Это может быть родительский класс или может быть совершенно несвязанным классом, который появляется в другом месте иерархии. – Steve Jessop 1 May 2009 в 16:41
  • 4
    Стив, большую часть времени он делает то, что наиболее разумно, например, когда вы сталкиваетесь с en.wikipedia.org/wiki/Diamond_problem . – Turion 24 July 2012 в 22:28
  • 5
  • 6
    Синтаксис super(Foo, self) для Python 2.x правильный? В Python 3.x предпочтительнее super()? – Trevor Boyd Smith 24 April 2017 в 12:18

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

class Foo(Bar):
    def __init__(self):
        super().__init__()
30
ответ дан Arun Ghosh 20 August 2018 в 23:22
поделиться
  • 1
    Приятно слышать, что у python 3 есть лучшее решение. Вопрос исходит от python 2.X. Спасибо за предложение. – jjohn 26 July 2016 в 15:53

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

Однако

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

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

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

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

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

21
ответ дан Ben 20 August 2018 в 23:22
поделиться
  • 1
    Это именно то, что я хочу знать. Благодаря :) – Chad 5 February 2018 в 09:43
  • 2
    @gizzmole, в какой ситуации это не работает? Я рад добавить любые оговорки или предупреждения, которые имеют отношение к делу, но я не мог понять, как ссылка, которую вы опубликовали, имеет отношение к этому ответу. – Ben 9 August 2018 в 13:12
  • 3
    @Ben Извините, я недостаточно внимательно прочитал ваш ответ. Этот ответ не отвечает на вопрос о том, как перегружать функции, но отвечает на другой вопрос. Я удалил свой первоначальный комментарий. – gizzmole 9 August 2018 в 13:42
  • 4
    @gizzmole ах, не беспокойтесь. Я понимаю, что этот ответ не относится к перегрузке функций, однако в вопросе явно не упоминается перегрузка (хотя приведенный пример perl показывает случай перегрузки). Подавляющее большинство других ответов охватывает перегрузку - это здесь для тех людей, которые в ней не нуждаются. – Ben 9 August 2018 в 14:55
  • 5

В Python 2 мне не повезло с super (). Я использовал ответ от jimifiki на этом SO thread как ссылаться на родительский метод в 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()'
5
ответ дан Community 20 August 2018 в 23:22
поделиться
  • 1
    Вы должны использовать class A(object): вместо class A():. Тогда super () будет работать – blndev 17 September 2017 в 16:50
  • 2
    Я не уверен, что буду следовать. Вы имеете в виду определение класса? Очевидно, вы должны указать, что у класса есть родитель, чтобы подумать, что вы можете обратиться к родителям! Поскольку я опубликовал это 9 месяцев назад, я немного неясен в деталях, но я думаю, что я имел в виду примеры из Arun Ghosh, lawrence, kkk и т. Д., Которые не применимы в Py 2.x. Вместо этого, вот метод, который работает и простой способ ссылаться на родителя, поэтому немного более понятно, что вы делаете. (например, используя супер) – BuvinJ 18 September 2017 в 12:37
ImmediateParentClass.frotz(self)

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

70
ответ дан industryworker3595112 20 August 2018 в 23:22
поделиться
  • 1
    Это означает, что ImmediateParentClass также присутствует в области действия этого оператора. Просто использование объекта, импортированного из модуля, не поможет. – Tushar Vazirani 14 March 2018 в 19:04
  • 2
    что, если это метод класса? – Shiplu Mokaddim 3 April 2018 в 15:57

Я бы рекомендовал использовать 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
ответ дан Joran Beasley 20 August 2018 в 23:22
поделиться
  • 1
    Я искал что-то, чтобы сказать мне базовые классы. Найдено здесь. Благодаря! – zVictor 9 May 2012 в 14:24
  • 2
    Имейте в виду, что, как вы можете сказать из объема ссылок на super здесь, люди действительно не хотят использовать базы , если вы не делаете что-то действительно глубокое. Если вам не нравится super , посмотрите на mro . Первую запись в mro безопаснее, чем отслеживать, какую запись в основах использовать. Множественное наследование в Python сканирует некоторые вещи назад, а другие направляются вперед, так что позволить языку расслабиться, этот процесс является самым безопасным. – Jon Jay Obermark 31 August 2014 в 16:31

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

Этот пример аналогичен один из которых описан выше. Однако есть одно отличие: супер не имеет аргументов, переданных ему. Этот выше код является исполняемым в версии python 3.4.

4
ответ дан kkk 20 August 2018 в 23:22
поделиться

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

class Foo(Bar):
    def __init__(self):
        super(Foo, self).__init__()
        self.baz = 5
13
ответ дан lawrence 20 August 2018 в 23:22
поделиться

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()
97
ответ дан MaBe 20 August 2018 в 23:22
поделиться
  • 1
    Лучший пример, чем Адам, потому что вы продемонстрировали использование класса нового стиля с базовым классом объекта. Просто отсутствует ссылка на классы нового стиля. – Samuel 9 January 2015 в 22:41

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

super(self.__class__,self).baz(arg)
-21
ответ дан user806071 20 August 2018 в 23:22
поделиться
  • 1
    self .__ class__ не работает правильно с супер, поскольку self всегда является экземпляром, а его класс всегда является классом экземпляра. Это означает, что если вы используете super (self .__ class__ .. в классе и этот класс унаследован от него, он больше не будет работать. – xitrium 23 August 2011 в 22:34
  • 2
    Чтобы подчеркнуть, НЕ ИСПОЛЬЗУЙТЕ ЭТОТ КОД. Он поражает всю цель super (), которая должна правильно пересекать MRO. – Eevee 6 February 2012 в 23:31
  • 3
    stackoverflow.com/a/19257335/419348 сказал, почему бы не позвонить super(self.__class__, self).baz(arg). – AechoLiu 21 August 2014 в 07:32

Вот пример использования функции 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
25
ответ дан yesnik 20 August 2018 в 23:22
поделиться
  • 1
    Разве это не плохой пример? Я считаю, что не супер безопасно использовать Super, если ваша целая иерархия не является «новым стилем». классов и правильного вызова Super (). init () – Jaykul 23 May 2014 в 16:04
-3
ответ дан shim 31 October 2018 в 18:22
поделиться
5
ответ дан Community 31 October 2018 в 18:22
поделиться
0
ответ дан Khan 31 October 2018 в 18:22
поделиться
Другие вопросы по тегам:

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