一, 复习
属性的的正确存放位置:
类中应该存储所有对象公共的内容
对象中存储都是每个对象独有的(都不同)
初始化函数:
给对象的属性赋初值 , 可以保证只要对象被创建就一定有相应的属性
节省了重复代码
绑定方法:
指的是 将类或对象与函数进行了绑定
之所以绑定是为了提高整合度,后续在拿到对象就可以直接调用而无需关心 数据是什么 如何处理
对象也可以看做是一个存储数据的容器
对象绑定方法:
默认情况下就是绑定给对象的
当执行该方法时,需要访问对象中的内容
当使用对象调用时 会自动传入对象本身作为第一个参数
用类来调用时就是一个普通函数 该怎么传就这么传
类绑定方法:
当执行该方法时,需要访问类中的内容而不需要对象中的内容
@classmethod
无论使用类还是对象来调用都会自动传入类本身作为第一个参数
非绑定方法
既不需要访问类中的内容 也不需要访问对象中的内容 那就作为非绑定方法 就是一个普通函数 没有自动传值的效果
@staticmethod
继承
说的是类与类之间的关系
存在基础关系后 子类可以直接使用父类已经存在的内容 总的来说是为了提高代码的复用性
例如猫 和狗 都属于动物类
描述的时 什么是什么的关系 如:猫是动物
要开始累积自己的类库 把经常使用的小功能写到一个模块中 以后可以直接调用
class 子类(父类):
pass
属性查找顺序
对象本身 -> 所在的类 -> 类的父类 -> .... object
抽象
使用基础时 应该先抽象 在继承
抽象指的是 把一系列类中的相同的特征和行为抽取 形成一个新的类 (公共父类)
派生
子类拥有与父类不同的内容
覆盖
子类出现了与父类完全相同的名字
一切皆对象
在py3里面所有东西全是对象 包括 int list 模块 函数 .....包等等....
list.append(li,1)
子类访问父类的内容
1.指名道姓 直接写死了类名 即时不存在继承关系也能调用
2.super().要访问的属性 (py3出现的)
3.super(这个子类的名字,self).属性
二 , 继承已有的类来扩展新功能
#实现一个存储类,在提供基本的存取功能之外,还要可以限制存储元素的类型
class MyList(list):
def __init__(self,element_cls):
#当你覆盖了init时,不要忘记调用super().init函数让父类完成原有的初始化操作
super().__init__()
self.element_cls = element_cls
def append(self,object):
if object.__class__ == self.element_cls: #如果传进来的数据与我限制的的类型匹配上,则添加到列表
super().append(object)
else:
print('只能存储%s类型!'%self.element_cls.__name__)
li = MyList(str)
li.append(10) #只能存储str类型!
li.append('123')
print(li) #['123']
三 , 多继承问题
class A:
def test(self):
print('from A')
super().test() #应该报错,但是执行成功了
class B:
def test(self):
print('from B')
class C(A,B):
pass
c = C()
c.test()
# from A
# from B
print(C.mro()) #[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
#问题:多继承时如果多个父类中出现了同名的属性/函数
#你不能用眼睛去判断查找顺序,需要使用mro列表去查看真正的继承顺序
#总结:super在访问父类属性时,是按照mro列表一层层往上找的
class A:
a = 1
pass
class B(A):
a = 2
pass
class C(A):
a = 3
pass
class D(A):
a = 4
pass
class E(B,C,D):
a = 5
pass
aa = E()
print(aa.a)
print(E.mro()) #[<class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>]
四 , 组合
'''
组合:
指的是一个类把另一个类作为自己的属性来使用,就称之为组合
当你定义一个类,并且这个类拥有某种类型的属性时,就称之为组合
组合描述的是:什么拥有什么的关系, 学生有书 学生有手机
继承描述的是:什么是什么的关系 麦兜是猪 猪猪侠也是猪
'''''
class PC:
def open_app(self,app_name):
print('open %s'% app_name)
class Student:
def __init__(self,PC,notbook):
self.PC = PC
self.notbook = notbook
pc = PC()
notbook = PC()
s = Student(pc,notbook)
s.PC.open_app('qq')
s.notbook.open_app('what')
# s.PC.open_app('ch')
五 , 菱形继承
# 在py2中 A就是一个经典类
# class A:
# pass
# 如果你的代码需要兼容py2 那应该显式的继承object 无论是直接还是间接继承
class B(object):
pass
class A(B):
pass
六 , 接口
'''
接口:就是一套协议规范
具体表现形式:有一堆函数,但是只明确了函数的名称,没有明确函数的具体表现
'''''
import abc
class USB(metaclass=abc.ABCMeta):
@abc.abstractmethod
def open(self):
pass
@abc.abstractmethod
def work(self):
pass
@abc.abstractmethod
def close(self):
pass
class Mouse(USB):
#实现接口规定的所有功能
def open(self):
print('mouse open')
def work(self):
print('mouse word')
def close(self):
print('mouse close')
class KeyBord:
def open(self):
print('KeyBoard open')
def work(self):
print("KeyBoard working...")
def close(self):
print("KeyBoard closed")
#问题是无法限制子类,必须真正的实现接口中的功能
class Camera(USB):
def open(self):
pass
def work(self):
pass
def close(self):
pass
class PC:
def device(self,usb_device):
usb_device.open()
usb_device.work()
usb_device.close()
#在实例化Camera abc模块就会检查Camera是否实现了所有的抽象方法,如果没有则无法实例化
c = Camera()
p = PC()
#创建一个鼠标设备
m = Mouse()
#创建一个键盘设备
key1 = KeyBord()
#链接到电脑上
p.device(m)
p.device(key1)
p.device(c)
七 , 抽象
'''
抽象类:具备抽象方法的类
抽象方法是,没有函数体的方法
抽象类的特点:不能直接实例化
'''''
import abc
class Test(metaclass=abc.ABCMeta):
@abc.abstractmethod
def say_hi(self):
pass
#可以有普通函数
def info(self):
print('my class is Test')
class TT(Test):
def say_hi(self):
print('i an TT obj')
# pass
t = TT()
t.info()
t.say_hi()
八 , 鸭子类型
class PC():
def conntent_device(self, usb_device):
usb_device.open()
usb_device.work()
usb_device.close()
class Mouse:
# 实现接口规定的所有功能
def open(self):
print("mouse opened")
def work(self):
print("mouse working...")
def close(self):
print("mouse closed")
mouse = Mouse()
pc = PC()
pc.conntent_device(mouse)
class KeyBoard:
def open(self):
print("KeyBoard opened")
def work(self):
print("KeyBoard working...")
def close(self):
print("KeyBoard closed")
key1 = KeyBoard()
# 如果key1的特征和行为都像USB设备 那就把它当做USB设备来使用
# 对于使用者而言可以不用关心这个对象是什么类,是如如何是实现,
pc.conntent_device(key1)
class Linux:
def read_data(self,device):
data = device.read()
return data
def write_data(self,device,data):
device.write(data)
class Disk:
def read(self):
print("disk reading....")
return "这是一个磁盘上的数据"
def write(self,data):
print("disk writing %s..." % data)
class UP:
def read(self):
print("disk reading....")
return "这是一个U盘上的数据"
def write(self,data):
print("disk writing %s..." % data)
l = Linux()
d = Disk()
data = l.read_data(d)
l.write_data(d,"这是一个数据....")
up1 = UP()
l.read_data(up1)
l.write_data(up1,"一个数据...")