使用超级()Python 3中VS的Python 2 - Python和延伸使用超级()Pyth

2019-05-13 22:26发布

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:

$ 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:

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

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:

 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)

Answer 1:

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


Answer 2:

在单继承情况下(当你继承只有一个类),您的新类继承的基类的方法。 这包括__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__AsuperA.__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保证,他们是所谓的只是一次。



Answer 3:

总之,他们是等价的。 让我们有一个历史的看法:

(1)首先,将函数如下所示。

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

(2)使代码更抽象(更便携)。 获得超一流的常用方法是发明出来的:

    super(<class>, <instance>)

和初始化函数可以是:

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

但是需要类和实例二者的明确传球打破DRY(不要重复自己)统治了一下。

(3)在V3。 这是更聪明,

    super()

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



Answer 4:

只需要有为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


Answer 5:

另外,涉及具有超强使用抽象类的python3实现()。 你应该记住,

超()。 初始化 (姓名,10)

具有相同的效果

人。 初始化 (个体经营,名称,10)

记得有超()一个隐藏的“自我”,所以同一个对象传递给超init方法和属性添加到调用它的对象。 因此super()被转换到Person ,然后如果包括隐藏自我,你得到上面的代码断枝。

from abc import ABCMeta, abstractmethod
class Person(metaclass=ABCMeta):
    name = ""
    age = 0

    def __init__(self, personName, personAge):
        self.name = personName
        self.age = personAge

    @abstractmethod
    def showName(self):
        pass

    @abstractmethod
    def showAge(self):
        pass


class Man(Person):

    def __init__(self, name, height):
        self.height = height
        # Person.__init__(self, name, 10)
        super().__init__(name, 10)  # same as Person.__init__(self, name, 10)
        # basically used to call the superclass init . This is used incase you want to call subclass init
        # and then also call superclass's init.
        # Since there's a hidden self in the super's parameters, when it's is called,
        # the superclasses attributes are a part of the same object that was sent out in the super() method

    def showIdentity(self):
        return self.name, self.age, self.height

    def showName(self):
        pass

    def showAge(self):
        pass


a = Man("piyush", "179")
print(a.showIdentity())


文章来源: Python extending with - using super() Python 3 vs Python 2