Python extending with - using super() Python 3 vs Python 2
最初我想问这个问题,但后来我发现它已经被人想到了…
在谷歌搜索中,我发现了这个扩展configparser的例子。以下内容适用于python 3:
1 2 3 4 5 6 7 8 9 | $ 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:
1 2 3 4 5 6 7 8 9 | >>> 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新类和旧类样式的文章(例如这里)。现在我想知道,我可以做到:
1 2 3 4 5 6 | 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""" |
但是,我不应该叫init吗?在python 2中,这是否等同于:
1 2 3 4 5 6 7 | 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) |
python 3中引入了
super() (没有参数)(与__class__ ):1super() -> same as super(__class__, self)所以这将是新样式类的python 2等价物:
1super(CurrentClass, self)对于旧样式类,可以始终使用:
1
2
3class Classname(OldStyleParent):
def __init__(self, *args, **kwargs):
OldStyleParent.__init__(self, *args, **kwargs)
在单个继承情况下(仅当您子类一个类时),您的新类继承基类的方法。这包括
如果引入多个继承(一次子类化多个类),事情就会变得复杂起来。这是因为如果有多个基类具有
在这种情况下,你真的应该使用
如果是这样的话,那么这也可以正常工作(在python 3中,但是您可以将其改写为python 2——它也有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 |
注意两个基类如何使用
因此,
因此,在
如果你不使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class A: def __init__(self): print('A') class B: def __init__(self): print('B') class C(A, B): pass C() #prints: #A |
要解决这个问题,您必须定义
1 2 3 4 | class C(A, B): def __init__(self): A.__init__(self) B.__init__(self) |
问题在于,在更复杂的MI树中,某些类的
简而言之,它们是等价的。让我们来看看历史:
(1)首先,函数看起来是这样的。
1 2 3 | class MySubClass(MySuperClass): def __init__(self): MySuperClass.__init__(self) |
(2)使代码更抽象(更可移植)。一种获得超级类的常用方法被发明如下:
1 | super(<class>, <instance>) |
init函数可以是:
1 2 3 | class MySubClassBetter(MySuperClass): def __init__(self): super(MySubClassBetter, self).__init__() |
但是,如果需要类和实例的显式传递,就需要打破一点干涸(不要重复自己)规则。
(3)V3。它更聪明,
1 | super() |
在大多数情况下是足够的。你可以参考http://www.python.org/dev/peps/pep-3135/
只需为python 3提供一个简单而完整的示例,大多数人现在似乎都在使用它。
1 2 3 4 5 6 7 8 9 10 11 12 | 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) |
给予
1 2 | 42 chickenman |
另一个python3实现涉及使用带有super()的抽象类。你应该记住
super().init(name, 10)
效果与
Person.init(self, name, 10)
记住super()中有一个隐藏的"self",所以同一个对象传递给superclass in it方法,属性被添加到调用它的对象中。因此,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 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()) |