Python, расширяющийся с помощью: (super) питона 3 vs python 2

Первоначально я хотел задать этот вопрос , но потом я обнаружил, что это уже было сказано раньше …

Я нашел этот пример расширения 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() 

Но не с python2:

 >>> 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 и 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) 

Заранее спасибо за то, что помогли мне разобраться.

3 Solutions collect form web for “Python, расширяющийся с помощью: (super) питона 3 vs python 2”

  • super() (без аргументов) был введен в Python 3:

     super() -> same as super(__class__, self) 

    так что это будет эквивалент Python 2 для классов нового стиля:

     super(CurrentClass, self) 
  • для классов старого стиля вы всегда можете использовать:

      class Classname(OldStyleParent): def __init__(self, *args, **kwargs): OldStyleParent.__init__(self, *args, **kwargs) 

В одном случае наследования (при подклассе только одного класса) ваш новый класс наследует методы базового класса. Это включает __init__ . Поэтому, если вы не определяете его в своем классе, вы получите его от базы.

Все начинает усложняться, если вы вводите множественное наследование (подклассификация более одного класса за раз). Это связано с тем, что если более одного базового класса имеет __init__ , ваш класс наследует только первый.

В таких случаях вы действительно должны использовать super если сможете, я объясню, почему. Но не всегда можно. Проблема в том, что все ваши базовые классы также должны использовать его (и их базовые классы, а также – все дерево).

Если это так, то это также будет работать правильно (в Python 3, но вы можете переработать его в Python 2 – он также имеет super ):

 class A: def __init__(self): print('A') super().__init__() class B: def __init__(self): print('B') super().__init__() class C(A, B): pass C() #prints: #A #B 

Обратите внимание, что оба базовых класса используют super даже если у них нет собственных базовых классов.

Что super делает: он вызывает метод из следующего класса в MRO (порядок разрешения метода). 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__ для вас.

 class A: def __init__(self): print('A') class B: def __init__(self): print('B') class C(A, B): pass C() #prints: #A 

Чтобы исправить это, вы должны определить C.__init__ :

 class C(A, B): def __init__(self): A.__init__(self) B.__init__(self) 

Проблема в том, что в более сложных MI-деревьях методы __init__ некоторых классов могут быть вызваны более одного раза, тогда как супер / MRO гарантируют, что они вызываются только один раз.

Короче говоря, они эквивалентны. Давайте посмотрим на историю:

(1), функция выглядит так.

  class MySubClass(MySuperClass): def __init__(self): MySuperClass.__init__(self) 

(2) сделать код более абстрактным (и более портативным). Выдуман общий метод получения Super-Class, например:

  super(<class>, <instance>) 

И функция init может быть:

  class MySubClassBetter(MySuperClass): def __init__(self): super(MySubClassBetter, self).__init__() 

Однако, требуя явной передачи как класса, так и экземпляра, немного нарушите правило DRY (Do not Repeat Yourself).

(3) в V3. Это более умный,

  super() 

достаточно в большинстве случаев. Вы можете обратиться к http://www.python.org/dev/peps/pep-3135/

  • Python, переопределение метода унаследованного класса
  • Django: удалить поле из подкласса Form
  • Избегайте наследовать сгенерированные атрибуты класса с помощью метакласса
  • Как инициализировать классы (а не экземпляры) в Python?
  • Как эффективно и систематически перегружать методы класса Python
  • Наследовать docstrings в наследовании класса Python
  • Переопределение свойств в python
  • Проблема переопределения свойства и метода Python: почему свойство subclass по-прежнему вызывает метод базового класса
  • Python - лучший язык программирования в мире.