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__
从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保证,他们是所谓的只是一次。
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