1.继承的另一种使用方式
实现一个存储类 在提供基本的存取功能之外 还要可以限制存储元素的类型
最常见的是直接继承一个已经存在的类
当你想要创建一个新的类 发现这个类中的一些 在某一个类中已经存在
那就没有必要从头开始写 ,可以直接继承已有的类 然后做补充
class School(list):
def __init__(self, element_cls):
# 当你覆盖了init方法时
# 不要忘记调用super().init函数让父类完成原有的初始化操作
super().__init__()
self.element_cls = element_cls
def append(self, obj):
# if isinstance(object,str) # 判断要存储的元素是否是指定类型
if obj.__class__ == self.element_cls:
super().append(obj)
else:
print('只能是%s' % self.element_cls.__name__)
# self.element_cls(__name__)
l = School(str)
l.append(12)
l.append('147')
print(l)
# 多继承
class A:
def test(self):
print('from a')
super().test()
class B:
def test(self):
print('from b')
pass
class C(A,B):
pass
c=C()
c.test()
print(C.mro())
# 当你使用super()函数时,
# Python会在MRO列表上继续搜索下一个类。
# 只要每个重定义的方法统一使用super()并只调用它一次
# ,那么控制流最终会遍历完整个MRO列表,
# 每个方法也只会被调用一次
(# 注意:使用super调用的所有属性,
# 都是从MRO列表当前的位置往后找,
# 千万不要通过看代码去找继承关系,一定要看MRO列表)
# 例子
class A():
# q=3
pass
class B(A):
# q=5
pass
class C(A):
q=9
pass
class D(B,C):
# q=15
pass
Q=D()
print(Q.q)
print(D.mro())
组合:
指的是 一个类把另一个类的对象作为自己的属性 就称之为组合
当你定义一个类 并且这个类拥有某种类型的属性时 就称之为组合
都是用用来重用代码的方式:
组合描述的是 什么拥有什么的关系 学生 有 书 学生有手机
基础描述的是 什么是什么的关系 麦兜是猪 猪猪侠也是猪
class Person:
def __init__(self, name):
self.name = name
p = Person('perry')
print(p.name)
'''例子'''
class PC:
def open_app(self, app_name):
print('open %s' % app_name)
class Student:
def __init__(self, PC, notebook):
self.PC = PC
self.notebook = notebook
pass
qw=PC()
notebook=PC()
st=Student(qw,notebook)
st.notebook.open_app('学电脑')
菱形继承
# 在py2中 A就是一个经典类
class A:
pass
# 如果你的代码需要兼容py2 那应该显式的继承object 无论是直接还是间接继承
class B(obj):
pass
class A(B):
pass
经典类与新式类
1.只有在python2中才分新式类和经典类,python3中统一都是新式类 2.在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类 3.在python2中,显式地声明继承object的类,以及该类的子类,都是新式类 3.在python3中,无论是否继承object,都默认继承object,即python3中所有类均为新式
经典类:
深度优先
新式类:
先深度 直到有一个公共父类时,查找其他路线(基于C3算法)
接口
接口就是一套协议规范
具体表现形式: 有一堆函数 但是只明确了函数的名称 没有明确函数具体实现
class USB:
def open(self):
pass
def close(self):
pass
def work(self):
pass
使用接口可以提高程序的扩展性
只要对象按照接口规定方法来实现,使用者就可以无差别使用所有对象
接口与抽象类
抽象:
指的是不清楚,不具体,看不懂的
抽象方法
指的是 没有函数体的方法 用@abc.abstractmethod 装饰器
如果类中具备抽象方法 那么这个类就称之为抽象类
抽象类的特点:
不能直接实例化 必须有子类覆盖了所有抽象方法后才能实例化子类
接口的区别:
接口是指只有方法声明而没有实现体 , 接口中所有方法都是抽象的
import abc
class Test(metaclass= abc.ABCMeta):
@abc.abstractmethod
def say_hi(self):
pass
class QW(Test):
def say_hi(self):
print('是 QW ')
q=QW()
q.say_hi()
如果接口的子类没有实现接口中的方法,那是没有任何意义的
抽象类之所以出现的意义:通过抽象类来强行限制子类必须覆盖所有的抽象方法
鸭子类型
说如果一个对象叫声像鸭子,走路像鸭子,长得像鸭子,那它就是鸭子
是python 推荐的方式,python不喜欢强行限制你
利用标准库中定义的各种‘与文件类似’的对象,尽管这些对象的工作方式像文件,但他们没有继承内置文件对象的方法
class PC():
def content_device(self,usb_device):
usb_device.open()
usb_device.work()
usb_device.close()
class Mouse:
# 实现接口规定的所有功能
def open(self):
print('mouse open')
def work(self):
print('mouse work')
def close(self):
print('mouse close')
mouse=Mouse()
pc=PC()
pc.content_device(mouse)
class KeyBoard:
def open(self):
print('KeyBoard open')
def work(self):
print('KeyBoard work')
def close(self):
print('KeyBoard close')
key=KeyBoard()
pc.content_device(key)