Python扩展 - 使用super()Python 3与Python 2

时间:2022-11-08 21:23:10

Originally I wanted to ask this question, but then I found it was already thought of before...

本来我想问这个问题,但后来我发现它已经被考虑过......

Googling around I found this example of extending configparser. The following works with Python 3:

谷歌搜索我发现这个扩展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()

But not with Python 2:

但不是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

Then I read a little bit on Python New Class vs. Old Class styles (e.g. here. And now I am wondering, I can do:

然后我读了一下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"""

But, shouldn't I call init? Is this in Python 2 the equivalent:

但是,我不应该打电话给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)

4 个解决方案

#1


113  

  • super() (without arguments) was introduced in Python 3 (along with __class__):

    在Python 3中引入了super()(不带参数)(以及__class__):

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

    so that would be the Python 2 equivalent for new-style classes:

    所以这将是新风格类的Python 2等价物:

    super(CurrentClass, self)
    
  • for old-style classes you can always use:

    对于旧式课程,您可以随时使用:

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

#2


31  

In a single inheritance case (when you subclass one class only), your new class inherits methods of the base class. This includes __init__. So if you don't define it in your class, you will get the one from the base.

在单个继承的情况下(当您仅为一个类创建子类时),新类继承基类的方法。这包括__init__。因此,如果你没有在你的课程中定义它,你将从基础中获得它。

Things start being complicated if you introduce multiple inheritance (subclassing more than one class at a time). This is because if more than one base class has __init__, your class will inherit the first one only.

如果引入多重继承(一次为多个类创建子类),事情就会变得复杂起来。这是因为如果多个基类具有__init__,则您的类将仅继承第一个基类。

In such cases, you should really use super if you can, I'll explain why. But not always you can. The problem is that all your base classes must also use it (and their base classes as well -- the whole tree).

在这种情况下,你应该真的使用super,如果可以,我会解释原因。但并非总能如此。问题是你的所有基类也必须使用它(以及它们的基类 - 整个树)。

If that is the case, then this will also work correctly (in Python 3 but you could rework it into Python 2 -- it also has super):

如果是这种情况,那么这也将正常工作(在Python 3中你可以将其重新编写为Python 2 - 它也有超级):

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

Notice how both base classes use super even though they don't have their own base classes.

注意两个基类如何使用super,即使它们没有自己的基类。

What super does is: it calls the method from the next class in MRO (method resolution order). The MRO for C is: (C, A, B, object). You can print C.__mro__ to see it.

超级的作用是:它从MRO中的下一个类调用方法(方法解析顺序)。 C的MRO是:(C,A,B,对象)。您可以打印C .__ mro__来查看它。

So, C inherits __init__ from A and super in A.__init__ calls B.__init__ (B follows A in MRO).

因此,C从A继承__init__,在A .__ init__中继承超级调用B .__ init __(B跟随MRO中的A)。

So by doing nothing in C, you end up calling both, which is what you want.

所以在C中什么都不做,你最终都会调用它们,这就是你想要的。

Now if you were not using super, you would end up inheriting A.__init__ (as before) but this time there's nothing that would call B.__init__ for you.

现在如果你没有使用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

To fix that you have to define C.__init__:

要解决这个问题,你必须定义C .__ init__:

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

The problem with that is that in more complicated MI trees, __init__ methods of some classes may end up being called more than once whereas super/MRO guarantee that they're called just once.

问题在于,在更复杂的MI树中,某些类的__init__方法可能不止一次被调用,而super / MRO保证它们只被调用一次。

#3


16  

In short, they are equivalent. Let's have a history view:

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

(1) at first, the function looks like this.

(1)首先,函数看起来像这样。

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

(2) to make code more abstract (and more portable). A common method to get Super-Class is invented like:

(2)使代码更抽象(更便携)。获得Super-Class的常用方法是:

    super(<class>, <instance>)

And init function can be:

而init函数可以是:

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

However requiring an explicit passing of both the class and instance break the DRY (Don't Repeat Yourself) rule a bit.

然而,要求显式传递类和实例会破坏DRY(不要重复自己)规则。

(3) in V3. It is more smart,

(3)在V3。它更聪明,

    super()

is enough in most case. You can refer to http://www.python.org/dev/peps/pep-3135/

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

#4


4  

Just to have a simple and complete example for Python 3, which most people seem to be using now.

只是为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)

gives

42
chickenman

#1


113  

  • super() (without arguments) was introduced in Python 3 (along with __class__):

    在Python 3中引入了super()(不带参数)(以及__class__):

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

    so that would be the Python 2 equivalent for new-style classes:

    所以这将是新风格类的Python 2等价物:

    super(CurrentClass, self)
    
  • for old-style classes you can always use:

    对于旧式课程,您可以随时使用:

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

#2


31  

In a single inheritance case (when you subclass one class only), your new class inherits methods of the base class. This includes __init__. So if you don't define it in your class, you will get the one from the base.

在单个继承的情况下(当您仅为一个类创建子类时),新类继承基类的方法。这包括__init__。因此,如果你没有在你的课程中定义它,你将从基础中获得它。

Things start being complicated if you introduce multiple inheritance (subclassing more than one class at a time). This is because if more than one base class has __init__, your class will inherit the first one only.

如果引入多重继承(一次为多个类创建子类),事情就会变得复杂起来。这是因为如果多个基类具有__init__,则您的类将仅继承第一个基类。

In such cases, you should really use super if you can, I'll explain why. But not always you can. The problem is that all your base classes must also use it (and their base classes as well -- the whole tree).

在这种情况下,你应该真的使用super,如果可以,我会解释原因。但并非总能如此。问题是你的所有基类也必须使用它(以及它们的基类 - 整个树)。

If that is the case, then this will also work correctly (in Python 3 but you could rework it into Python 2 -- it also has super):

如果是这种情况,那么这也将正常工作(在Python 3中你可以将其重新编写为Python 2 - 它也有超级):

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

Notice how both base classes use super even though they don't have their own base classes.

注意两个基类如何使用super,即使它们没有自己的基类。

What super does is: it calls the method from the next class in MRO (method resolution order). The MRO for C is: (C, A, B, object). You can print C.__mro__ to see it.

超级的作用是:它从MRO中的下一个类调用方法(方法解析顺序)。 C的MRO是:(C,A,B,对象)。您可以打印C .__ mro__来查看它。

So, C inherits __init__ from A and super in A.__init__ calls B.__init__ (B follows A in MRO).

因此,C从A继承__init__,在A .__ init__中继承超级调用B .__ init __(B跟随MRO中的A)。

So by doing nothing in C, you end up calling both, which is what you want.

所以在C中什么都不做,你最终都会调用它们,这就是你想要的。

Now if you were not using super, you would end up inheriting A.__init__ (as before) but this time there's nothing that would call B.__init__ for you.

现在如果你没有使用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

To fix that you have to define C.__init__:

要解决这个问题,你必须定义C .__ init__:

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

The problem with that is that in more complicated MI trees, __init__ methods of some classes may end up being called more than once whereas super/MRO guarantee that they're called just once.

问题在于,在更复杂的MI树中,某些类的__init__方法可能不止一次被调用,而super / MRO保证它们只被调用一次。

#3


16  

In short, they are equivalent. Let's have a history view:

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

(1) at first, the function looks like this.

(1)首先,函数看起来像这样。

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

(2) to make code more abstract (and more portable). A common method to get Super-Class is invented like:

(2)使代码更抽象(更便携)。获得Super-Class的常用方法是:

    super(<class>, <instance>)

And init function can be:

而init函数可以是:

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

However requiring an explicit passing of both the class and instance break the DRY (Don't Repeat Yourself) rule a bit.

然而,要求显式传递类和实例会破坏DRY(不要重复自己)规则。

(3) in V3. It is more smart,

(3)在V3。它更聪明,

    super()

is enough in most case. You can refer to http://www.python.org/dev/peps/pep-3135/

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

#4


4  

Just to have a simple and complete example for Python 3, which most people seem to be using now.

只是为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)

gives

42
chickenman