Python学习之路(12)——绑定方法、未绑定方法以及子类调用父类方法
Python面向对象编程中有三种重要的概念:继承、重写和多态
这里我们主要讨论一下重写的概念。
先看一个例子,假如存在一个基类Person与子类Student,其中子类重写了父类的构造函数__init__(),运行时会报以下错误:
>>> class Person(object):
def __init__(self):
self.name = "Tom"
def getName(self):
return self.name
>>> class Student(Person):
def __init__(self):
self.age = 12
def getAge(self):
return self.age
>>> stu = Student()
>>> stu.getName()
Traceback (most recent call last):
File "<pyshell#41>", line 1, in <module>
stu.getName()
File "<pyshell#33>", line 5, in getName
return self.name
AttributeError: 'Student' object has no attribute 'name'
>>>
这是因为尽管Student类继承了Person类,但是并没有调用父类Person的__init__()方法,那么这种情况下如何调用父类的方法呢?
有两种解决方案:调用未绑定的父类构造方法;使用super()函数。
这里先解释一下什么叫绑定方法和未绑定方法。
bound和unbound方式其实是个很简单的概念。
在讯多语言当中,类似于a.b()这样的调用方法实际是一个整体,但是在Python中,它其实是两部分:获取属性a.b,调用()。所以也可以写成:
c = a.b c()
跟直接调用a.b()是等效的。当a是某个类的实例,b是这个类的方法的时候,a.b的返回值就是bound method,也就是绑定方法。它实际上是bound method对象,这个对象提前将self参数进行了绑定。如示例:
>>> class foo():
def hehe(self):
pass
>>> foo.hehe
<function foo.hehe at 0x0000000003588C80>
>>> a=foo()
>>> a.hehe
<bound method foo.hehe of <__main__.foo object at 0x0000000003543048>>
>>> foo.hehe()
Traceback (most recent call last):
File "<pyshell#17>", line 1, in <module>
foo.hehe()
TypeError: hehe() missing 1 required positional argument: 'self'
>>>
>>>
>>> a.hehe()
>>>
>>> foo.hehe(a)
>>>
相应的,如果A是一个类对象,b是该类的方法,A.b的返回值就是普通函数(Python3.x中为普通函数,Python2.x中为未绑定方法unbound method),这个函数有一个参数self,所以可以用A.b(a)的方式调用,也就是手工将self参数指定为a。这就是unbound method的用法。
1、方法一:调用未绑定的父类构造方法
>>> class Person(object): def __init__(self): self.name = "Tom" def getName(self): return self.name >>> class Student(Person): def __init__(self): Person.__init__(self) #调用未绑定的父类构造方法 self.age = 12 def getAge(self): return self.age >>> stu = Student() >>> stu.getName() 'Tom' >>>
2、方法二:使用super()函数
>>> class Person(object): def __init__(self): self.name = "Tom" def getName(self): return self.name >>> class Student(Person): def __init__(self): super(Student, self).__init__() # 使用super()函数 self.age = 12 def getAge(self): return self.age >>> stu = Student() >>> stu.getName() 'Tom'
super()函数会返回一个super对象,该对象负责进行方法解析,解析过程会自动查找所有的父类以及父类的父类,其最大的优点是如果子类继承了多个父类,只需要使用一次super()函数即可。
而直接调用未绑定方法的方式更加直观。
浙公网安备 33010602011771号