2012-05-07 40 views
57

本来我想问问this question,但后来我发现的时候,已经想到过的......Python的延伸 - 使用超()的Python 3比Python的2

周围的Googling我发现extending 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的新类与旧类样式一点点(如here 现在我。我想,我可以这样做:

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""" 

但是,我不应该叫初始化这是在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) 
+1

在你的榜样,你不需要定义一个'__init __()'的子类,如果它是所有调用超类'__init __()'(以Python 2或3) - 而是让超级继承。 – martineau

+0

有用的参考资料:http://amyboyle.ninja/Python-Inheritance/ –

回答

99
  • super()(不带参数)在Python 3引入(连同__class__):

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

    所以这将是Python的2当量新样式类:

    super(CurrentClass, self) 
    
  • 您可以随时使用的旧式课程:

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

-1。这个答案没有为我澄清任何事情。在Python 2中,'super(__ class __)'给出了'NameError:全局名'__class__'未定义','super(self .__ class __)'也是错误的。你*必须*提供一个实例作为第二个参数,这意味着你需要做'super(self .__ class__,self)',但这是错误的**。如果'Class2'继承自'Class1'并且'Class1'调用'super(self。__class__,self).__ init __()','Class1'''__init__'然后*在实例化'Class2'的实例时调用它自己*。 – jpmc26

+0

为了澄清一点,当试图在Python 2中调用'super(self .__ class __)'时,我得到'TypeError:super()至少需要1个参数(0给出)'。(这没有什么意义)但是它显示了这个答案中缺少多少信息。) – jpmc26

+2

@ jpmc26:在python2中,你得到这个错误是因为你试图调用'__init __()'而没有绑定超级对象的参数(通过调用'super( self .__ class __)'只有一个参数),你需要一个绑定的超级对象,那么它应该工作:'super(CurrentClass,self).__ init __()'。不要使用'self .__ class__',因为在调用父类时它总是引用_same_类,因此如果该父类也执行相同的操作,则会创建一个无限循环。 – mata

28

在单个继承的情况下(当您仅继承一个类时),您的新类将继承基类的方法。这包括__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中的下一个类(方法解析顺序)调用方法。 C的MRO是:(C, A, B, object)。您可以打印C.__mro__以查看它。

所以,CA.__init__电话B.__init__B遵循MRO A)继承Asuper__init__

因此,通过在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保证他们只被调用一次。

+7

'请注意,即使基类没有自己的基类,两个基类都使用超类。“他们有。在py3k中,每个类的子类都是对象。 – akaRem

15

总之,它们是等价的。我们有一个历史视图:

(1)起初,函数看起来像这样。 (2)使代码更抽象(并且更便于携带)。获得超一流的常用方法是发明出来的:

super(<class>, <instance>) 

和初始化函数可以是:

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

但是需要类和实例二者的明确传球打破DRY(别重复你自己)规则一点。 (3)在V3中,可以使用以下公式(3):

(3)。它更智能,

super() 

在大多数情况下是足够的。你可以参考http://www.python.org/dev/peps/pep-3135/

0

只是为了一个Python 3的简单和完整的例子,大多数人似乎现在正在使用它。

class MySuper(object): 
    def __init__(self,a): 
     self.a = a 

class MySub(MySuper): 
    def __init__(self,a,b): 
     self.b = b 
     super().__init__(a) 

my_sub = MySub(42,'chickenman') 
print(my_sub.a) 
print(my_sub.b) 

42 
chickenman