继承是面向对象的重要特性之一,作为面向对象的Python,接下来让我们探讨一下Python的继承机制
为什么继承?
减少代码的重复性,提高代码的复用性
能继承什么?
- 公有属性
- 公有方法
怎么继承?
了解了python中类的基础知识后,让我们看一下神奇的继承机制
python中继承的基本格式如下:
#父类
class superClassName:
pass
#子类
class subClassName(superClassName):
pass
子类需要继承父类的构造方法时,必须显示的调用,并传递参数 self
# -*- coding: utf-8 -*-
class People:
def __init__(self, name, age):
self.__name = name
self.__age = age
def getName(self):
return self.__name
def getAge(self):
return self.__age
class Xiaonan(People):
def __init__(self, name, age):
#注意要显示调用父类构造方法,并传递参数self
People.__init__(self, name, age)
xn = Xiaonan('xioaonan', 20)
print xn.getName() #xiaonan
print xn.getAge() #20
需要注意的有以下几点:
- 如果父类和子类都重新定义了构造方法
__init()__
,子类实例化时,子类的构造方法不会自动调用父类的构造方法,必须在子类中显示调用。 - 如果需要在子类中调用父类的方法,需要以 "父类名.方法" 这种方式调用,以这种方式调用的时候,注意要传递
self
参数过去。
# -*- coding: utf-8 -*-
class People:
def __init__(self, name, age):
self.__name = name
self.__age = age
def getName(self):
return self.__name
def getAge(self):
return self.__age
def Miss(self):
print "I miss you in People"
class Xiaonan(People):
def __init__(self, name, age):
People.__init__(self, name, age)
def InSub(self):
People.Miss()
xn = Xiaonan('xioaonan', 20)
print xn.getName()
print xn.getAge()
xn.InSub()
运行结果为:
xioaonan
20
Traceback (most recent call last):
File "test.py", line 28, in <module>
xn.InSub()
File "test.py", line 23, in InSub
People.Miss()
TypeError: unbound method Miss() must be called with People instance as first argument (got nothing instead)
- 子类继承了父类所有的公有属性和方法,可以在子类中通过父类名来调用,而对于私有的属性和方法,子类是不进行继承的,因此在子类中是无法通过父类名来访问的。
# -*- coding: utf-8 -*-
class People:
height = 170
__money = 10
def __init__(self, name, age):
self.__name = name
self.__age = age
def getName(self):
return self.__name
def getAge(self):
return self.__age
def Miss(self):
print "I miss you in People"
def __say(self):
print "I can say in People"
class Xiaonan(People):
def __init__(self, name, age):
People.__init__(self, name, age)
def InSub(self):
print People.height
People.Miss(self)
print People.__money
# People.__say(self)
xn = Xiaonan('xioaonan', 20)
print xn.getName()
print xn.getAge()
xn.InSub()
运行结果为:
xioaonan
20
170
I miss you in People
Traceback (most recent call last):
File "test.py", line 37, in <module>
xn.InSub()
File "test.py", line 31, in InSub
print People.__money
AttributeError: class People has no attribute '_Xiaonan__money'
将 print People.__money
这一行注释,下面一行打开时,同样的报错类型:
Traceback (most recent call last):
File "ss1.py", line 37, in <module>
xn.InSub()
File "ss1.py", line 32, in InSub
People.__say(self)
AttributeError: class People has no attribute '_Xiaonan__say'
python 支持多重继承
# -*- coding: utf-8 -*-
class People:
def __init__(self, name, age):
self.__name = name
self.__age = age
def getName(self):
return self.__name
def getAge(self):
return self.__age
class Student:
def __init__(self, className, sno):
self.className = className
self.sno = sno
def getClass(self):
return self.className
def getSno(self):
return self.sno
class Xiaonan(People, Student):
def __init__(self, name, age, className, sno):
People.__init__(self, name, age)
Student. __init__(self, className, sno)
self.money = 100
xn = Xiaonan('xioaonan', 20, '软件班', 201158761)
print xn.getName() #xiaonan
print xn.getSno() #201158761
print xn.money #100
多重继承始终以第一个父类中为中心:
- 当子类中未申明构造方法时,将自动调用第一个父类的构造方法
# -*- coding: utf-8 -*-
class People:
def __init__(self, name, age):
self.__name = name
self.__age = age
def getName(self):
return self.__name
def getAge(self):
return self.__age
def eat(self):
print 'I am having lunch'
class Student:
def __init__(self, className, sno):
self.className = className
self.sno = sno
def getClass(self):
return self.className
def getSno(self):
return self.sno
def eat(self):
print 'I am having dinner'
class Xiaonan(People, Student):
money = 100
xn = Xiaonan('xioaonan', 20)
print xn.getName()
print xn.getClass()
运行结果:
xioaonan
Traceback (most recent call last):
File "test.py", line 38, in <module>
print xn.getClass()
File "test.py", line 24, in getClass
return self.className
AttributeError: Xiaonan instance has no attribute 'className'
不难看出,的确调用的是第一个父类的构造方法
- 若多个父类中有含有同名的方法时,通过子类的实例化对象调用该方法,则调用的是第一个父类的该方法
# -*- coding: utf-8 -*-
class People:
def __init__(self, name, age):
self.__name = name
self.__age = age
def getName(self):
return self.__name
def getAge(self):
return self.__age
def eat(self):
print 'I am having lunch'
class Student:
def __init__(self, className, sno):
self.className = className
self.sno = sno
def getClass(self):
return self.className
def getSno(self):
return self.sno
def eat(self):
print 'I am having dinner'
class Xiaonan(People, Student):
money = 100
xn = Xiaonan('xioaonan', 20)
print xn.eat()
运行结果为
I am having lunch
None