Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python扩展-使用super()Python 3 vs Python 2_Python_Inheritance_Configparser - Fatal编程技术网

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

Python扩展-使用super()Python 3 vs Python 2,python,inheritance,configparser,Python,Inheritance,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): .

本来我想问的,但后来我发现以前已经想到了

在谷歌上搜索,我发现了这个例子。以下内容适用于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
但是,我不应该叫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)

在单一继承的情况下(当您只对一个类进行子类化时),您的新类继承基类的方法。这包括
\uuuu init\uuuu
。因此,如果您不在类中定义它,您将从基中得到一个

如果引入多重继承(一次对多个类进行子类化),事情就会变得复杂起来。这是因为如果有多个基类具有
\uuuu init\uuuu
,则您的类将只继承第一个基类

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

如果是这种情况,那么它也可以正常工作(在Python 3中,但您可以将其重新编写为Python 2——它还有
super
):

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

super
所做的是:它从MRO(方法解析顺序)中的下一个类调用方法。
C
的MRO是:
(C,A,B,object)
。您可以打印
C.\uu mro\uu
来查看它

因此,
C
A
super
中继承了
\uu初始化

因此,如果在
C
中不执行任何操作,您最终会同时调用这两个函数,这正是您想要的

现在,如果您没有使用
super
,您将最终继承
A.\uuuu init\uuuu
(与以前一样),但这次没有任何东西可以为您调用
B.\uu init\uuu

class A:
    def __init__(self):
        print('A')

class B:
    def __init__(self):
        print('B')

class C(A, B):
    pass

C()
#prints:
#A
要解决这个问题,您必须定义
C.\uuuu init\uuuu

class C(A, B):
    def __init__(self):
        A.__init__(self)
        B.__init__(self)
super() -> same as super(__class__, self)
问题是,在更复杂的MI树中,某些类的
\uuuu init\uuuu
方法可能会被多次调用,而super/MRO保证它们只被调用一次。

  • (不带参数)是在Python 3中引入的(与
    \uuuuu class\uuuu
    一起):

    因此,对于新样式的类来说,这就是Python 2的等价物:

    super(CurrentClass, self)
    
  • 对于旧式类,您始终可以使用:

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

    • 简而言之,它们是等价的。 让我们看一看历史:

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

          class MySubClass(MySuperClass):
              def __init__(self):
                  MySuperClass.__init__(self)
      
      (2) 使代码更抽象(更可移植)。发明了一种获取超级类的常用方法,如:

          super(<class>, <instance>)
      
      但是,需要显式地传递类和实例会稍微打破干式(不要重复)规则

      (3) 在V3中。它更聪明

          super()
      

      在大多数情况下,这已经足够了。您可以参考

      来获得一个简单而完整的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)
      
      给予


      另一个python3实现涉及使用super()的抽象类。你应该记住这一点

      super().__init__(name, 10)
      
      具有与相同的效果

      Person.__init__(self, name, 10)
      
      请记住,super()中有一个隐藏的“self”,因此同一个对象将传递给超类init方法,并将属性添加到调用它的对象中。 因此,
      super()

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

      注意两个基类如何使用super,即使它们没有自己的基类。
      它们有。在py3k中,每个类都是对象的子类。这是我一直在寻找的答案,但不知道如何提问。MRO描述很好。在您的示例中,如果子类所做的只是调用超类“
      \uuuu init\uu()
      (在Python 2或3中),则不需要在子类中定义一个
      \uuu init\uu()
      ”,而只需继承超类即可。具有更正链接的有用参考:-1。这个回答没有为我澄清任何事情。在Python2中,
      super(\uuuuuu class\uuuu)
      给出了
      NameError:global name'\uuuu class\uuuuuu'没有定义
      super(self.\uuuuu class\uuuuu)
      也是错误的。您必须提供一个实例作为第二个参数,这将建议您需要执行
      super(self.\uuuu class\uuuuu,self)
      ,但这是错误的。如果
      Class2
      继承自
      Class1
      并且
      Class1
      调用
      super(self.\uuuu class\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
      在Python2中尝试调用super(self.\uuuu class\uuuuuuu)
      时。(这没有多大意义,但它说明了这个答案中缺少多少信息。)@jpmc26:在python2中,你会遇到这个错误,因为你试图在未绑定的超级对象上调用
      \uuuu init\uuu()
      (通过调用
      super(self.\uu class\uuuuuu)
      而没有参数(只调用一个参数),您需要一个绑定的超级对象,然后它应该工作:
      super(CurrentClass,self)。\uuu init\uuuu()
      。不要使用
      self.\uuuuuu class\uuuuuu
      ,因为调用父级时,它将始终引用同一个类,因此如果父级也这样做,则会创建一个无限循环。
      \uuuuu class\uuuuu
      (成员)也存在于Python2中。@CristiFati这不是关于
      \uuuuuu class\uuuuuuu
      成员的,而是关于始终引用当前定义的类的,Python2中不存在的。PEP链接非常有用,谢谢!
      42
      chickenman
      
      super().__init__(name, 10)
      
      Person.__init__(self, name, 10)
      
      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())