25 继承 多继承 组合 菱形继承 接口 鸭子类型

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)

  






原文地址:https://www.cnblogs.com/komorebi/p/10883413.html