6.7 类的继承
所谓类的继承(inheritance),就是新类继承旧类的属性与方法,这种行为称为派生子类(subclassing)。继承的新类称为派生类(derived class),被继承的旧类则称为基类(base class)。当用户创建派生类后,就可以在派生类内新增或是改写基类的任何方法。
派生类的语法如下:
class <类名称> [(基类1,基类2, ...)]: ["文件字符串"] <语句>
一个派生类可以同时继承自许多个基类,基类之间以逗号(,)隔开。
下列是一个基类A与一个基类B:
>>> class A: pass >>> class B: pass
下列是一个派生类C,继承自一个基类A:
>>> class C(A): pass
下列是一个派生类D,继承自两个基类A与B:
>>> class D(A, B): pass
1.派生类的构造方法
下列是一个基类的定义:
>>>class Student: def __init__(self, name, sex, phone): self.name = name self.sex = sex self.phone = phone def printData(self): print ("姓名: ", self.name) print ("性别: ", self.sex) print ("电话: ", self.phone)
这个基类Student有3个成员变量:name(姓名)、sex(性别)和phone(电话)。并且定义两个函数:①__init__()函数是Student类的构造方法。②printData()函数用来打印成员变量的数据。下面创建一个Student类的派生类:
>>>class Person(Student): def __init__(self, name, sex, phone): #派生类的构造方法 Student.__init__(self, name, sex, phone) #调用基类的构造方法
派生类的构造方法必须调用基类的构造方法,而且必须使用完整的基类名称。Student.__init__(self, name, sex, phone)中的self参数,用来告诉基类现在调用的是哪一个派生类。
下列案例创建一个派生类Person的实例变量,并且调用基类Student的函数printData(),来印出数据。
>>>x = Person("李明峰", "男", "12345678") >>>x.printData() 姓名: 李明峰 性别: 男 电话: 12345678
2.命名空间的搜索顺序
当用户在类内编写函数时,要记得类函数的命名空间的搜索顺序。
(1)类的实例。
(2)类。
(3)基类。
下列是3个类:A、B和C。B继承自A, C又继承自B。A、B、C这3个类都有一个相同名称的函数printName()。代码如下:
>>> class A: def __init__(self, name): self.name = name def printName(self): print ("这是类A的printName()函数,name = %s" % self.name) >>>class B(A): def __init__(self, name): A.__init__(self, name) def printName(self): print ("这是类B的printName()函数,name = %s" % self.name) >>> class C(B): def __init__(self, name): B.__init__(self, name) def printName(self): print ("这是类C的printName()函数,name = %s" % self.name)
下面分别创建A、B、C这3个类的实例,并且调用printName()函数。代码如下:
>>> A("张晓晓").printName() 这是类A的printName()函数,name = 张晓晓 >>> B("胡明月").printName() 这是类B的printName()函数,name = 胡明月 >>> C("张一诺").printName() 这是类C的printName()函数,name = 张一诺
上述代码分析如下。
(1)A("张晓晓").printName()会调用A类的printName()函数。
(2)B("胡明月").printName()会先调用B类的printName()函数,因为已经找到一个printName()函数,所以不会继续往A类查找。
(3)C("张一诺").printName()会先调用C类的printName()函数,因为已经找到一个printName()函数,所以不会继续往B类与A类查找。
3.类的多继承
Python同样有限的支持多继承形式。
【案例6-2】类的多继承(代码6.2.py)。
#类定义 class people: #定义基本属性 name = '' age = 0 #定义私有属性,私有属性在类外部无法直接进行访问 __weight = 0 #定义构造方法 def __init__(self, n, a, w): self.name = n self.age = a self.__weight = w def speak(self): print("%s说:我 %d岁。" %(self.name, self.age)) #单继承示例 class student(people): grade = '' def __init__(self, n, a, w, g): #调用父类的构函 people.__init__(self, n, a, w) self.grade = g #覆写父类的方法 def speak(self): print("%s说:我 %d岁了,我在读 %d年级 "%(self.name, self.age, self.grade)) #另一个类,多重继承之前的准备 class speaker(): topic = '' name = '' def __init__(self, n, t): self.name = n self.topic = t def speak(self): print("我叫 %s,我是一名人民教师,我演讲的主题是 %s"%(self.name, self.topic)) #多重继承 class sample(speaker, student): a ='' def __init__(self, n, a, w, g, t): student.__init__(self,n,a,w,g) speaker.__init__(self,n,t) test = sample("张明明",25,80,4, "什么是爱") test.speak() #方法名同,默认调用的是在括号中靠前的父类的方法
保存并运行程序,结果如下:
C:\Users\Administrator>python d:\python\ch06\6.2.py 我叫 张明明,我是一名人民教师,我演讲的主题是 什么是爱
在本案例中,定义了一个people类,定义一个student类继承自people类,实现单继承效果。为了实现多继承效果,这里又定义了一个speaker类,然后定义sample类继承自speaker类和student类。