Изначально я хотел задать этот вопрос , но потом обнаружил, что об этом уже думали раньше ...
Погуглив, я нашел этот пример расширения configparser . Следующее работает с Python 3:
$ python3
Python 3.2.3rc2 (default, Mar 21 2012, 06:59:51)
[GCC 4.6.3] on linux2
>>> from configparser import SafeConfigParser
>>> class AmritaConfigParser(SafeConfigParser):
... def __init_(self):
... super().__init__()
...
>>> cfg = AmritaConfigParser()
Но не с Python 2:
>>> class AmritaConfigParser(SafeConfigParser):
... def __init__(self):
... super(SafeConfigParser).init()
...
>>> cfg = AmritaConfigParser()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __init__
TypeError: must be type, not classob
Затем я прочитал немного о стилях Python New Class vs. Old Class (например, здесь . И теперь мне интересно, я могу:
class MyConfigParser(ConfigParser.ConfigParser):
def Write(self, fp):
"""override the module's original write funcition"""
....
def MyWrite(self, fp):
"""Define new function and inherit all others"""
Но разве я не должен вызывать init? Это эквивалент в Python 2:
class AmritaConfigParser(ConfigParser.SafeConfigParser):
#def __init__(self):
# super().__init__() # Python3 syntax, or rather, new style class syntax ...
#
# is this the equivalent of the above ?
def __init__(self):
ConfigParser.SafeConfigParser.__init__(self)
__init__()
в подклассе, если все, что он делает, это вызывает суперкласс__init__()
(в Python 2 или 3) - вместо этого просто позвольте суперклассу унаследоваться.Ответы:
super()
(без аргументов) был введен в Python 3 (вместе с__class__
):так что это будет эквивалент Python 2 для классов нового стиля:
для классов старого стиля вы всегда можете использовать:
источник
super(__class__)
даетNameError: global name '__class__' is not defined
и такжеsuper(self.__class__)
является ошибочным. Вы должны предоставить экземпляр в качестве второго аргумента, который предполагает, что вам нужно это сделатьsuper(self.__class__, self)
, но это неверно . ЕслиClass2
наследуется отClass1
иClass1
вызововsuper(self.__class__, self).__init__()
,Class1
«s__init__
будет называть себя , когда инстанцирование экземпляраClass2
.TypeError: super() takes at least 1 argument (0 given)
при попытке вызватьsuper(self.__class__)
Python 2. (Что не имеет большого смысла, но демонстрирует, сколько информации отсутствует в этом ответе.)__init__()
без аргумента несвязанного супер объекта (который вы получите по телефонуsuper(self.__class__)
только с одним аргументом), вам нужен связанный объект супер , то он должен работать:super(CurrentClass, self).__init__()
. Не используйте,self.__class__
потому что это всегда будет относиться к одному и тому же классу при вызове родителя и, следовательно, создать бесконечный цикл, если этот родитель также делает то же самое.__class__
(член) также существует в Python2 .__class__
члене, а о неявно созданном лексическом__class__
замыкании, которое всегда относится к классу, определяемому в данный момент, которого нет в python2.В одном случае наследования (когда вы подклассифицируете только один класс) ваш новый класс наследует методы базового класса. Это включает
__init__
. Так что, если вы не определите его в своем классе, вы получите его из базы.Все начинает усложняться, если вы вводите множественное наследование (создание подклассов более чем одного класса за раз). Это связано с тем, что если их несколько
__init__
, ваш класс унаследует только первый.В таких случаях вам действительно стоит использовать,
super
если вы можете, я объясню почему. Но не всегда получается. Проблема в том, что все ваши базовые классы также должны использовать его (и их базовые классы - все дерево).Если это так, то это также будет работать правильно (в Python 3, но вы можете переработать его в Python 2 - он также есть
super
):Обратите внимание, как используются оба базовых класса,
super
хотя у них нет собственных базовых классов.Что
super
делает: он вызывает метод из следующего класса в MRO (порядок разрешения методов). МРО заC
это:(C, A, B, object)
. Вы можете распечатать,C.__mro__
чтобы увидеть это.Итак,
C
наследуется__init__
отA
иsuper
вA.__init__
вызовахB.__init__
(B
следуетA
в MRO).Так что, ничего не делая
C
, вы в конечном итоге вызываете оба, чего вы и хотите.Теперь, если бы вы не использовали
super
, вы бы в конечном итоге унаследовалиA.__init__
(как и раньше), но на этот раз нет ничего, что могло быB.__init__
вас заинтересовать.Чтобы исправить это, вам нужно определить
C.__init__
:Проблема заключается в том, что в более сложных деревьях MI
__init__
методы некоторых классов могут вызывать более одного раза, тогда как super / MRO гарантирует, что они вызываются только один раз.источник
Notice how both base classes use super even though they don't have their own base classes.
У них есть. В py3k каждый объект подкласса класса.Короче говоря, они эквивалентны. Давайте посмотрим на историю:
(1) сначала функция выглядит так.
(2) сделать код более абстрактным (и более переносимым). Распространенный метод получения суперкласса изобретается примерно так:
И функция инициализации может быть:
Однако требование явной передачи как класса, так и экземпляра немного нарушает правило DRY (Don't Repeat Yourself).
(3) в V3. Это умнее,
в большинстве случаев достаточно. Вы можете обратиться к http://www.python.org/dev/peps/pep-3135/
источник
Просто чтобы иметь простой и полный пример для Python 3, который, похоже, сейчас используется большинством людей.
дает
источник
Еще одна реализация python3, которая включает использование абстрактных классов с super (). Вы должны помнить это
имеет тот же эффект, что и
Помните, что в super () есть скрытое «я». Таким образом, тот же объект передается методу инициализации суперкласса, и атрибуты добавляются к объекту, который его вызвал. Следовательно,
super()
переводится в,Person
а затем, если вы включаете скрытое я, вы получаете приведенный выше фрагмент кода.источник