美文网首页简友广场想法散文
python抽象类、接口、泛函数、适配器模式

python抽象类、接口、泛函数、适配器模式

作者: Cache_wood | 来源:发表于2021-12-01 09:35 被阅读0次

@[toc]

抽象类

type()函数
  • 并非仅仅返回对象的类型
  • Python使用type()函数创建类对象
    函数和类不是编译时定义的,而是在运行时动态创建
  • type()函数依次传入3个参数
    • 类名称
    • 继承的父类集合(tuple)
    • 属性(数据或方法)字典
def say_hello(self):
    print(f"hi,I am {self.name}")

def __init__(self,name):
    self.name=name

People=type('People',(object,),dict(say_hello=say_hello,__init__=__init__))
p=People('zjc')
p.say_hello()

hi,I am zjc
元类
  • 控制类的创建行为
    • 先定义metaclass,然后创建类,最后创建实例
    • 类可以看成metaclass创建的“实例”
  • 元类的定义
    • metaclass的类名总是以Metaclass结尾
    • metaclass是类的模板,所以必须从type类型派生
  • 元类的使用
    • 通过关键字参数metaclass来指定元类来创建类
def add(self,value):
    self.append(value)

class ListMetaClass(type):  #定义元类
    def __new__(cls,name,bases,attrs):
        attrs['add']=add
        return type.__new__(cls,name,bases,attrs)

class Mylist(list,metaclass=ListMetaClass):#创建类,可以看做是元类的实例
    pass

l=Mylist()
l.add(1)
l.add(2)
print(l)

[1, 2]
  • 有时需要动态定义类
    • Object Relational Mapping(ORM)
    • 关系数据库的一行映射为一个实例对象,也就是一
    个类对应一个表
    • “透明化”数据库相关的操作
    • 类需要动态定义
抽象类

特殊的类,只能被继承,不能被实例
从不同的类中抽取相同的属性和行为

  • 抽象类与普通类的区别
    – 抽象类中有抽象方法
    – 不能被实例化,只能被继承
    – 子类必须实现抽象方法
import abc #借助abc模块实现抽象类

class Fruit(metaclass=abc.ABCMeta):#class Fruit(abc.ABC)
    @abc.abstractmethod
    def harvest(self):
        pass

    @abc.abstractmethod
    def grow(self):
        pass

class Apple(Fruit):  #子类必须实现基类的方法,否则装饰器会报错
    
    def harvest(self):
        print("从树上摘")

    def grow(self):
        print("种苹果树")

    def juice(self):
        print("做苹果汁")

class Watermelon(Fruit):  #继承抽象类
    def harvest(self):
        #super().harvest()
        print("从地里摘")

    def grow(self):
        print("用种子种")

@Fruit.register
class Orange: #注册抽象类
    def harvest(self):
        print("从树上摘")
    
    def grow(self):
        print("种橘子树")

#f=Fruit()
a=Apple()
a.grow()
w=Watermelon()
w.harvest()

o=Orange()
o.grow()

print(isinstance(o,Fruit))
print(issubclass(Orange,Fruit))
print([sc.__name__ for sc in Fruit.__subclasses__()]) #no orange
种苹果树
从地里摘
种橘子树
True
True
['Apple', 'Watermelon']
[<class '__main__.Apple'>, <class '__main__.Watermelon'>]

接口

python中没有专门的支持
任何方法都只是一种规范,具体的功能需要子类实现
与抽象类的区别

  • 抽象类中可以对一些抽象方法做出基础实现
  • 接口中所有方法只是规范,不做任何实现

泛函数

  • 函数对不同的参数类型会提供不同的处理方式
  • 通过装饰器来实现
  • 类似于重载机制

适配器模式 Adapter

  • 将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题
  • 目标类 Target
    定义客户所需的接口,可以是一个抽象类或接口,也可以是具体类
  • 适配器类 Adapter
    转换器,通过调用另一个接口对Adaptee和Target进行适配
  • 适配者类 Adaptee
    被适配类,包括了客户期待的业务方法
import abc
class Computer:
    def __init__(self,name):
        self._name=name

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self,value):
        self._name=value

    def __str__(self):
        return 'the {} computer'.format(self._name)

    def execute(self):
        print('execute a computer program')

class Human:
    def __init__(self,name):
        self._name=name
    def __str__(self):
        return '{} is an human'.format(self._name)
    def speak(self):
        print('hello word from human')

class Synthesizer:
    def __init__(self,name):
        self._name=name
    def __str__(self):
        return 'the {} synthesizer'.format(self._name)
    def play(self):
        print('play a synthesizer')

class Target(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def execute(self):
        pass

class HumanAdapter(Target):
    def __init__(self,human):
        self.human=human

    def execute(self):
        self.human.speak()

class SynthesizerAdapter(Target):
    def __init__(self,syn):
        self.syn=syn
    def execute(self):
        self.syn.play()

#另一种实现策略
class Adapter:
    def __init__(self,adp_obj,adp_methods):
        self.obj=adp_obj
        self.__dict__.update(adp_methods)

    def __str__(self):
        return str(self.obj)

def main():

    objects=[Computer('mac')]
    syn=Synthesizer('yamaha')
    h=Human('zjc')

    objects.append(HumanAdapter(h))
    objects.append(SynthesizerAdapter(syn))
    for obj in objects:
        obj.execute()
    print()

    objects2=[Computer('mac')]
    objects2.append(Adapter(syn,dict(execute=syn.play)))
    objects2.append(Adapter(h,dict(execute=h.speak)))
    for obj in objects2:
        obj.execute()

if __name__=='__main__':main()
execute a computer program
hello word from human
play a synthesizer

execute a computer program
play a synthesizer
hello word from human

相关文章

  • python抽象类、接口、泛函数、适配器模式

    @[toc] 抽象类 type()函数 并非仅仅返回对象的类型 Python使用type()函数创建类对象函数和类...

  • Java接口

    抽象类,抽象方法 接口 策略设计模式 适配器模式 多继承 接口的继承 接口中的域 接口与工厂

  • class 类

    基本用法 构造函数和this 继承 抽象类 接口(TypeScript 独有) 属性的封装 泛型

  • 设计模式之适配器模式

    适配器模式: 类适配器模式、对象适配器模式、接口适配器模式 1.类适配器模式:新的接口出现了,但是和老的接口不兼容...

  • php设计模式(三)适配器模式

    适配器模式 适配器模式将截然不同的函数接口封装成统一的api 实际应用:php数据操作有mysql、mysqli、...

  • 适配器模式

    适配器模式主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。适配器模式将某个类的接口转换成客户端期...

  • 【Dart】Dart类与对象

    类与对象 类 继承 抽象类 接口 混入 泛型 枚举类类-简介 构造器 (构造函数) 默认构造函数与类同名的函数,在...

  • 代理 & 适配器 & 装饰模式 对比

    代理 & 适配器 & 装饰模式 对比 适配器模式 vs 代理模式适配器模式: 提供一个不同的接口(如不同版本的接口...

  • Java设计模式(二)

    talk is cheap show me the code 适配器模式 类适配器模式 接口适配器模式 对象适配器...

  • 适配器模式

    适配器模式,可以将截然不同的函数接口封装成统一的API适配器模式,即根据客户端需要,将某个类的接口转换成特定样式的...

网友评论

    本文标题:python抽象类、接口、泛函数、适配器模式

    本文链接:https://www.haomeiwen.com/subject/wwldxrtx.html