面向对象三大特性:封装、继承、多态
封装
封装就是用特殊的语法,对成员属性和成员方法进行包装,达到保护和隐藏的目的
但是封装是为了限制一些访问和操作,不能全部限制
被封装的成员只是限制了访问的权限,并不是不让访问
通常情况下,被封装的成员主要是提供内部使用
# 封装
'''
被特殊语法封装的成员,会有不同的访问权限,主要供内部使用
封装的级别:
公有:public 受保护:_protected 私有:__private
类外部是否可以访问 Y Y(python可以) N
'''
class Person():
# 成员属性
name = None
_age = None
__address = None
# 成员方法
def _say(self):
print('hello python')
def sing(self):
print('唱歌')
def __eat(self):
print('吃饭')
def __init__(self, name, age, address):
self.name = name
self.age = age
self.address = address
tim = Person('python', 12, '北京') # {'name': 'python', 'age': 12, 'address': '北京'}
# 对象的所有成员属性
print(tim.__dict__)
# 对象所有可执行方法
print(tim.__dir__()) # ['name', 'age', 'address', '__module__', 'say', 'sing', 'eat', '__init__', '__dict__',。。。。]
print(tim.name) # None
print(tim._age) # hello python
tim._say()
# tim.__eat() 报错
# print(tim.__address) # 报错
继承
计算机中的继承
在面向对象中,一个类继承了父类,那么这个类就拥有了父类中所有的成员(除私有成员)
继承概念
被其它类继承的类,称为父类也叫做基类或者超类
继承类叫做子类,或者派生类
继承的意义
提高代码的复用性,建立新的类与类的关系,方便其它逻辑的操作
语法格式
class 父类():
pass
class 子类(父类):
pass
继承的特征:
-
不指定继承父类时,所有类都继承Object
-
子类继承父类后就拥有了父类中的所有成员属性和成员方法 (除了私有化成员和方法)
-
子类继承父类后只是引用父类的成员属性和方法,并不是父类
-
子类继承父类后可以重写父类中的成员方法,叫做方法的重写
-
重写父类方法后,子类可以使用super().func()方式继续调用父类被重写的方法
-
子类如果定义了父类中不存在的方法,叫做对父类的扩展
# 继承
'''
当子类继承父类后,就可以使用父类的成员属性和方法(除私有成员)
子类可以有自己独立的成员
子类继承父类后,重新定义了父类中的方法,这种情况称为对父类方法的重写
子类继承父类后,定义父类中没有的方法,称为对父类的扩展
一个父类可以被多个子类继承
子类调用父类的方法时,如果该方法有参数要求,也需要传递参数
'''
import time
# 定义猫科动物
class Felidae():
# 属性
color = '花色'
sex = 'man'
def running(self):
print('奔跑的猫科动物')
def eat(self):
print('吃饭的小猫')
# 定义猫类
class Cat(Felidae):
# 定义私有属性
age = 11
# 重写父类方法
def eat(self):
print('子类重写父类的小猫吃饭方法')
# 在子类中使用被子类重写的父类方法
super().eat() # 吃饭的小猫
# 扩展父类方法
def play(self):
print('小猫在玩老鼠')
# 实例化对象
c = Cat()
print(c.__dict__) # {}
print(c.color) # 花色
c.running() # 奔跑的猫科动物
c.eat() # 子类重写父类的小猫吃饭方法
c.play() # 小猫在玩老鼠
# 使用私有属性
print(c.age) # 11
单继承和多继承
单继承
一个类只能继承一个父类
一个父类可以被多个子类继承,还可以存在链式继承
链式继承:继承父类的子类后子类被另外子类继承 (B被A继承,A被C继承)
多继承
一个类可以继承多个父类
语法格式:
class 父亲():
pass
class母亲():
pass
....
class 子类(父亲,母亲,...):
pass
# 多继承
# 父亲类
class F():
def sing(self):
print('父亲在唱歌')
class M():
def sing(self):
print('母亲在唱歌')
class Sun(F, M):
def sing(self):
# Sun(F,M),F在前时默认调用F
super().sing() # 类父亲在唱歌
print('儿子在唱歌')
# 实例化对象
s = Sun()
s.sing() # 儿子在唱歌
菱形继承(钻石继承)
A
B D
C
# 菱形继承
# 爷爷类
class HuMan():
age = 60
def sing(self):
print('爷爷在唱歌')
# 父亲类
class F(HuMan):
age = 35
def sing(self):
super().sing()
print(super().age)
print('父亲在唱歌')
# 母亲类
class M(HuMan):
age = 33
def sing(self):
super().sing()
print(super().age)
print('母亲在唱歌')
# 儿子类
class Sun(F, M):
age = 5
def sing(self):
super().sing()
print(super().age)
print('儿子在唱歌')
s = Sun()
s.sing()
'''
继承关系:
s-->F-->M--HuMan
print结果:
爷爷在唱歌
60
母亲在唱歌
33
父亲在唱歌
35
儿子在唱歌
'''
#mro() 获取MRO列表,就是类的继承关系
print(Sun.mro()) # [<class '__main__.Sun'>, <class '__main__.F'>, <class '__main__.M'>, <class '__main__.HuMan'>, <class 'object'>]
MRO(MRP Reation Prder)
MRO列表生成原则:
1.子类永远在父类的前面
2.同等级的类,按照子类继承顺序排序
3.先子类后父类的顺序原则,最后的类是系统提供的Object类
[<class '__main__.Sun'>, <class '__main__.F'>, <class '__main__.M'>, <class '__main__.HuMan'>, <class 'object'>]
super()
super()在调用时,并不是查找父类,而是去MRO列表找上一个类
super()在调用时,会自动把当前self传入到上一级的类的方法中
类关系检测 issubclass()
issubclass() 检测一个类是否是另外一个类的子类
class A():
print('A类')
class B(A):
print('B类')
class C(B):
print('C类')
class D(C):
print('D类')
res = issubclass(B, A) # 检查B类是不是A类的子类 True
print(res)
res = issubclass(D, A) # 检查S类是不是A类的子类 True
print(res)
res = issubclass(A, C) # 检查A类是不是C类的子类 False
print(res)
多态
同一个方法,调用的对象不同,产生了不同形态的结果,这种现象叫做多态
普通写法实现
# 多态
# 同一个方法,调用的对象不同,产生了不同形态的结果,这种现象叫做多态
# 定义电脑类
class Computer():
# 在电脑类中定一个usb的规范接口 方法,在方法中传递一个对象,实现多态功能
def usb(self, obj):
obj.start()
# 定义鼠标类
class Mousr():
def start(self):
print('鼠标插入成功,可以正常使用')
# 定义键盘类
class KeyBord():
def start(self):
print('键盘接入成功,可以正常启动')
# 定义U盘类
class UDisk():
def start(self):
print('U盘接入成功,可以正常使用')
# 实例化对象
c = Computer() # 电脑对象
m = Mousr() # 鼠标对象
k = KeyBord() # 键盘对象
u = UDisk() # U盘对象
# 把不同的设备插入到电脑的usb接口中
c.usb(m) # 鼠标插入成功,可以正常使用
c.usb(k) # 键盘接入成功,可以正常启动
c.usb(u) # U盘接入成功,可以正常使用
继承方法实现
# 多态 继承版
"""
定义一个接口规范类,其它类都继承这个类,并重新父类的方法
由于每一个对象都实现父类方法的方式都不同,最后的结果也是不一样的
"""
# 定义USB类
class USB():
"""
当前类说明:
这个类只是一个接口规范类,需要子类继承并实现start方法
start方法不做任何具体功能的实现
"""
# 在接口中规定一个规范的接方法,但不实现功能
def start(self):
pass
# 定义鼠标类
class Mousr(USB):
def start(self):
print('鼠标接入成功,可以正常使用')
# 定义键盘类
class KeyBord(USB):
def start(self):
print('键盘接入成功,可以正常启动')
# 定义U盘类
class UDisk(USB):
def start(self):
print('U盘接入成功,可以正常使用')
# 实例化对象
c = Computer() # 电脑对象
m = Mousr() # 鼠标对象
k = KeyBord() # 键盘对象
u = UDisk() # U盘对象
m.start() # 鼠标接入成功,可以正常使用
k.start() # 键盘接入成功,可以正常启动
u.start() # U盘接入成功,可以正常使用