最近看代码对于super一直有些迷惑,然后看了一些资料,下面整理一下相关内容。(参考《python语言及其应用》以及菜鸟教程)
首先子类中可以覆盖父类的方法,但是如果想调用父类的方法就需要使用super().
super() 方法的语法:
super(type[, object-or-type])
参数说明:
- type -- 类
- object-or-type -- 类,一般是 self
下面定义一个新的类EmailPerson,用于表示有电子邮箱的Person。首先定义Person类:
class Person:
def __init__(self,name):
self.name=name
下面定义一个子类,子类的初始化方法_init__()中添加一个额外的email参数:
class EmailPerson(Person):
def __init__(self,name,email):
super().__init__(name)
self.email=email
在子类中定义_init__()方法时,父类_init__()方法会被覆盖。因此,在子类中,父类的初始化方法并不会被自动调用,必须限时显式调用它,以上代码实际上做了这样的几件事:
- 通过super()方法获取了父类Person的定义。
- 子类的_init__()调用了Person._init__()方法。它会自动将self参数传递给父类。因此,你只需传入其他参数即可。在上面的例子中,Person()能接受的其余参数指的是name。
- self.email=email这行的新的代码才真正起到了将 EmailPerson和Person区分开的作用。
下面创建一个 EmailPerson类的对象:
bob = EmailPerson('Bob Frapples','bob@frapples.com')
我们既可以访问name特性,也可以访问email特性:
为什么不能像下面这样定义EmailPerson类呢?
class EmailPerson(Person):
def __init__(self,name,email):
self.name = name
self.email = email
确实可以这样做,但这有悖我们使用继承的初衷。我们应该使用super()来让Person完成它应该做的事情,就像任何一个单独的Person对象一样。除此之外,不这么写还有另一个好处:如果Person类的定义在未来发生改变,使用super()可以保证这次改变会自动反映到EmailPerson类上,而不需要手动修改。子类可以按照自己的方式处理问题,但如果仍需要借助父类的帮助,使用super()是最佳选择。
需要注意的是,super()在Python3.x 和 Python2.x 的一个区别是: Python 3 可以使用直接使用super().xxx代替super(Class, self).xxx,下面给出两个例子来说明:
Python3.x:
#Python3.x
class A:
def add(self, x):
y = x+1
print(y)
class B(A):
def add(self, x):
super().add(x)
b = B()
b.add(2) # 3
Python2.x:
#Python2.x
class A(object): # Python2.x 记得继承 object
def add(self, x):
y = x+1
print(y)
class B(A):
def add(self, x):
super(B, self).add(x)
b = B()
b.add(2) # 3
给出一个完整的例子:
class FooParent(object):
def __init__(self):
self.parent = 'I'm the parent.'
print ('Parent')
def bar(self,message):
print ("%s from Parent" % message)
class FooChild(FooParent):
def __init__(self):
# super(FooChild,self) 首先找到 FooChild 的父类(就是类 FooParent),然后把类 FooChild 的对象转换为类 FooParent 的对象
super(FooChild,self).__init__()
print ('Child')
def bar(self,message):
super(FooChild, self).bar(message)
print ('Child bar fuction')
print (self.parent)
if __name__ == '__main__':
fooChild = FooChild()
fooChild.bar('HelloWorld')
运行结果: