Python中常用的设计模式

2023-11-02

主要参考网址:http://www.pythontip.com/pythonPatterns/

创建型模式:

1、抽象工厂模式

class PetShop:
    def __init__(self,animal_factory=None):
        self.pet_factory = animal_factory

    def show_pet(self):
        pet = self.pet_factory.get_pet()
        print("This is a lovely",pet)

class Dog:
    def speak(self):
        return "woof"

    def __str__(self):
        return "Dog"

class Cat:
    def speak(self):
        return "meow"

    def __str__(self):
        return "Cat"

class DogFactory:
    def get_pet(self):
        return Dog()

class CatFactory:
    def get_pet(self):
        return Cat()

if __name__ == "__main__":
    shop = PetShop()
    shop.pet_factory = CatFactory()
    shop.show_pet()
    

2、单例模式

方法一:使用模块,模块是天生的单例模式,把相关的函数和数据定义在一个模块中,导入模块就可以获得一个单例对象了

方法二:使用装饰器

def Singleton(cls):
    _instance = {}

    def _singleton(*args, **kargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kargs)
        return _instance[cls]

    return _singleton


@Singleton
class A(object):
    a = 1

    def __init__(self, x=0):
        self.x = x


a1 = A(2)
a2 = A(3)

方法三:基于__new__:

import threading
class Singleton(object):
    _instance_lock = threading.Lock()

    def __init__(self):
        pass


    def __new__(cls, *args, **kwargs):
        if not hasattr(Singleton, "_instance"):
            with Singleton._instance_lock:
                if not hasattr(Singleton, "_instance"):
                    Singleton._instance = object.__new__(cls)  
        return Singleton._instance

obj1 = Singleton()
obj2 = Singleton()
print(obj1,obj2)

def task(arg):
    obj = Singleton()
    print(obj)

for i in range(10):
    t = threading.Thread(target=task,args=[i,])
    t.start()

方法四:基于metaclass

1.类由type创建,创建类时,type的__init__方法自动执行,类() 执行type的 __call__方法(类的__new__方法,类的__init__方法)
2.对象由类创建,创建对象时,类的__init__方法自动执行,对象()执行类的 __call__ 方法

import threading

class SingletonType(type):
    _instance_lock = threading.Lock()
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            with SingletonType._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)
        return cls._instance

class Foo(metaclass=SingletonType):
    def __init__(self,name):
        self.name = name


obj1 = Foo('name')
obj2 = Foo('name')
print(obj1,obj2)

3、原型模式

import copy


class Prototype:
    def __init__(self):
        self._objects = {}

    def register_object(self, name, obj):
        """Register an object"""
        self._objects[name] = obj

    def unregister_object(self, name):
        """Unregister an object"""
        del self._objects[name]

    def clone(self, name, **attr):
        """Clone a registered object and update inner attributes dictionary"""
        obj = copy.deepcopy(self._objects.get(name))
        obj.__dict__.update(attr)
        return obj


def main():
    class A:
        pass

    a = A()
    prototype = Prototype()
    prototype.register_object('a', a)
    b = prototype.clone('a', a=1, b=2, c=3)

    print(a)
    print(b.a, b.b, b.c)


if __name__ == '__main__':
    main()

结构型模式:

1、适配器模式

class Dog:
    def speak(self):
        return "woof"

    def __str__(self):
        return "Dog"

class Cat:
    def speak(self):
        return "meow"

    def __str__(self):
        return "Cat"

class Adaptor:
    def __init__(self,obj,adapted_methods):
        self.obj= obj
        self.__dict__.update(adapted_methods)
    def __getattr__(self,attr):
        return getattr(self.obj,attr)

if __name__ == "__main__":
    objects = []
    dog = Dog()
    objects.append(Adaptor(dog,dict(make_noise=dog.speak)))
    
    for obj in objects:
        print(obj,obj.make_noise())

2、装饰模式

class foo(object):
    def f1(self):
        print("original f1")

    def f2(self):
        print("original f2")


class foo_decorator(object):
    def __init__(self, decoratee):
        self._decoratee = decoratee

    def f1(self):
        print("decorated f1")
        self._decoratee.f1()

    def __getattr__(self, name):
        return getattr(self._decoratee, name)

u = foo()
v = foo_decorator(u)
v.f1()
v.f2()

3、代理模式

class SalesManager:
    def work(self):                         
        print("Sales Manager working...")             

    def talk(self):                         
        print("Sales Manager ready to talk") 


class Proxy:
    def __init__(self):                         
        self.busy = 'No'                         
        self.sales = None             

    def work(self):
        print("Proxy checking for Sales Manager availability")                         
        if self.busy == 'No':                                      
            self.sales = SalesManager()                                      
            time.sleep(2)
            self.sales.talk()                         
        else:                                      
            time.sleep(2)
            print("Sales Manager is busy")


if __name__ == '__main__':
    p = Proxy()
    p.work()
    p.busy = 'Yes'
    p.work()

4、外观模式

import time

SLEEP = 0.5


# Complex Parts
class TC1:
    def run(self):
        print("###### In Test 1 ######")
        time.sleep(SLEEP)
        print("Setting up")
        time.sleep(SLEEP)
        print("Running test")
        time.sleep(SLEEP)
        print("Tearing down")
        time.sleep(SLEEP)
        print("Test Finished\n")


class TC2:
    def run(self):
        print("###### In Test 2 ######")
        time.sleep(SLEEP)
        print("Setting up")
        time.sleep(SLEEP)
        print("Running test")
        time.sleep(SLEEP)
        print("Tearing down")
        time.sleep(SLEEP)
        print("Test Finished\n")


class TC3:
    def run(self):
        print("###### In Test 3 ######")
        time.sleep(SLEEP)
        print("Setting up")
        time.sleep(SLEEP)
        print("Running test")
        time.sleep(SLEEP)
        print("Tearing down")
        time.sleep(SLEEP)
        print("Test Finished\n")


# Facade
class TestRunner:
    def __init__(self):
        self.tc1 = TC1()
        self.tc2 = TC2()
        self.tc3 = TC3()
        self.tests = [i for i in (self.tc1, self.tc2, self.tc3)]

    def runAll(self):
        [i.run() for i in self.tests]


# Client
if __name__ == '__main__':
    testrunner = TestRunner()
    testrunner.runAll()

行为型模式:

1、观察者模式

class Subject(object):
    def __init__(self):
        self._observers = []

    def attach(self, observer):
        if not observer in self._observers:
            self._observers.append(observer)

    def detach(self, observer):
        try:
            self._observers.remove(observer)
        except ValueError:
            pass

    def notify(self, modifier=None):
        for observer in self._observers:
            if modifier != observer:
                observer.update(self)


# Example usage
class Data(Subject):
    def __init__(self, name=''):
        Subject.__init__(self)
        self.name = name
        self._data = 0

    @property
    def data(self):
        return self._data
    
    @data.setter
    def data(self, value):
        self._data = value
        self.notify()


class HexViewer:
    def update(self, subject):
        print('HexViewer: Subject %s has data 0x%x' %
              (subject.name, subject.data))


class DecimalViewer:
    def update(self, subject):
        print('DecimalViewer: Subject %s has data %d' %
              (subject.name, subject.data))


# Example usage...
def main():
    data1 = Data('Data 1')
    data2 = Data('Data 2')
    view1 = DecimalViewer()
    view2 = HexViewer()
    data1.attach(view1)
    data1.attach(view2)
    data2.attach(view2)
    data2.attach(view1)

    print("Setting Data 1 = 10")
    data1.data = 10
    print("Setting Data 2 = 15")
    data2.data = 15
    print("Setting Data 1 = 3")
    data1.data = 3
    print("Setting Data 2 = 5")
    data2.data = 5
    print("Detach HexViewer from data1 and data2.")
    data1.detach(view2)
    data2.detach(view2)
    print("Setting Data 1 = 10")
    data1.data = 10
    print("Setting Data 2 = 15")
    data2.data = 15


if __name__ == '__main__':
    main()

2、访问者模式

class Node(object):
    pass


class A(Node):
    pass


class B(Node):
    pass


class C(A, B):
    pass


class Visitor(object):
    def visit(self, node, *args, **kwargs):
        meth = None
        for cls in node.__class__.__mro__:
            meth_name = 'visit_'+cls.__name__
            meth = getattr(self, meth_name, None)
            if meth:
                break

        if not meth:
            meth = self.generic_visit
        return meth(node, *args, **kwargs)

    def generic_visit(self, node, *args, **kwargs):
        print('generic_visit '+node.__class__.__name__)

    def visit_B(self, node, *args, **kwargs):
        print('visit_B '+node.__class__.__name__)


a = A()
b = B()
c = C()
visitor = Visitor()
visitor.visit(a)
visitor.visit(b)
visitor.visit(c)

3、模板模式

ingredients = "spam eggs apple"
line = '-' * 10


# Skeletons
def iter_elements(getter, action):     
    """Template skeleton that iterates items"""      
    for element in getter():         
        action(element)     
        print(line)  


def rev_elements(getter, action):
    """Template skeleton that iterates items in reverse order"""      
    for element in getter()[::-1]:         
        action(element)     
        print(line)  


# Getters
def get_list():     
    return ingredients.split()  


def get_lists():
    return [list(x) for x in ingredients.split()]  


# Actions
def print_item(item):     
    print(item)  


def reverse_item(item):
    print(item[::-1])  


# Makes templates
def make_template(skeleton, getter, action):     
    """Instantiate a template method with getter and action"""     
    def template():         
        skeleton(getter, action)     
    return template  

# Create our template functions 
templates = [make_template(s, g, a)              
             for g in (get_list, get_lists)              
             for a in (print_item, reverse_item)              
             for s in (iter_elements, rev_elements)]  

# Execute them 
for template in templates:     
    template()

4、迭代器模式

def count_to(count):
    """Counts by word numbers, up to a maximum of five"""
    numbers = ["one", "two", "three", "four", "five"]
    # enumerate() returns a tuple containing a count (from start which
    # defaults to 0) and the values obtained from iterating over sequence
    for pos, number in zip(range(count), numbers):
        yield number

# Test the generator
count_to_two = lambda: count_to(2)
count_to_five = lambda: count_to(5)

print('Counting to two...')
for number in count_to_two():
    print(number, end=' ')

print()

print('Counting to five...')
for number in count_to_five():
    print(number, end=' ')

print()

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python中常用的设计模式 的相关文章

随机推荐

  • JavaWeb项目中如何让后端的数据传递到前端(包括JSP、JS)

    后端传递给前端的方式很多 如果是后端传递给JSP 我想大家很多人都知道 可以使用 后端可以使用 req setAttribute msg msg 前端可以使用 或者用JSP的el表达式比如 msg 这边小编重点讲讲如何在JS和后端通信 如果
  • 混杂设备动态次设备号分析

    今天看驱动源码时 发现一个MISC DYNAMIC MINOR宏 于是分析了一下内核源码 先粘出源码 在misc register函数中 有如下语句 if misc gt minor MISC DYNAMIC MINOR int i DYN
  • 开始使用OpenCV

    开始使用OpenCV 1 编译OpenCV 1 1 使用命令行的方式配置OpenCV OpenCV官网教程 OpenCV官网教程使用命令行的方式进行配置 写的很详细 按照教程操作 一般都能成功 由于国内访问GitHub不稳定 所以推荐使用w
  • Python 微信机器人

    使用python构造一个微信聊天机器人 最近在学python的过程中无意间发现一个python库 wxpy 其可以实现让微信自动接收 处理消息并进行回复的一系列功能 感觉挺有意思的 便自行摸索学习 并成功地实现了其功能 故写下此博客作学习分
  • 谷歌浏览器插件Automa(入门,编写中,开专栏填坑中)

    谷歌浏览器插件Automa 入门 编写中 0 待成长的无代码化爬虫 1快速入门模块 1 1 中文设置 1 2 定位你想要操作的位置 1 3 进行操作 1 3 1 点击 1 3 2 输入 1 4 官方案例实战教学 1 4 1 百歌一下 1 4
  • spring boot 2.0.3 mybatis升级mybatis-plus

    项目原来是使用mybtais durid 现升级为mybatis plus2 3 durid mysql 官方文档地址 请注意 mybatis plus3 0 的配置有变化 请查看官网文档 可能是旧的 或demo 步骤如下 1 引入pom
  • Linux中文件的传输

    文件在系统中的传输 1 scp 上传 scp 本地文件 远程主机用户 远程主机ip 远程主机目录 步骤如下 下载 scp 远程主机用户 远程主机ip 远程主机目录 本地目录 步骤如下 2 rsync 远程同步 速度快 默认会忽略 文件属性
  • 【AnyQ】遇到的问题整理(一)

    一 编译出错 问题描述 In file included from home jockeyyan git repository QuestionAnsweringBot AnyQ build third party paddle src e
  • 分布式计算的基本原理

    author skate time 2010 03 08 从最近几次MMI设计会议讨论的结果来看 嵌入式程序员对于分布式计算知之甚少 他们对分布式计算有种恐惧 所以对分布式架构极力排斥 而他们的人数又占绝对优势 讨论N次 MMI的架构还是没
  • Jupyter Notebook 工作环境配置

    目录 背景 为什么要配置jupyter的工作环境呢 因为可以更方便的找到自己写的脚本所在的文件 步骤 1 新建一个文件夹 随便在哪里建 例如我在D盘新建了一个文件夹 D pythonworkspace 2 接下来配置环境变量 新建一个变量W
  • mysql的sql语句获取两点之间的距离

    一张表 表的经度和维度都为double或者decimal类型 传入参数经度116 366216 纬度39 939834 SELECT ROUND 6378 138 2 ASIN SQRT POW SIN 40 0497810000 PI 1
  • 真难!!!Java初中级岗位都能被卷到怀疑人生....

    Java一个初中级岗位有上千人同时竞争 内卷程度简直怀疑人生 最近不少群友吐槽 初中级岗位的面试简直是地狱级难度 面试官对常用框架的考察扣的都很细 但是在日常开发中又很难注意到这些细节 导致吃了很多亏 其实说到底 还是这个问题 主流框架都熟
  • SQL查询重复数据出现的次数

    背景 关系型数据库中 有这样一种情况 假设用户信息表中有一列idCard字段 该字段用来存储用户的身份证号 现在导入进来一批数据后有人告诉你库里存在重复的数据 那么此时 你需要重复的规则是什么 到底是哪列关键数据出现了重复 首先人名重复的情
  • JVM - 的类加载器(类加载子系统)

    文章目录 类加载子系统 Class Loader 作用 类加载过程 加载阶段 Loding 连接阶段 Linking 验证 Verification 准备 Preparation 解析 Resolution 初始化 Initializati
  • InsightFace_Pytorch人脸识别项目部署运行

    一 下载InsightFace Pytorch master 二 导入各种包 三 运行take pic py搜集样本 四 运行face verify py识别 遇到问题解决方法 1 导包失败 需使用python3 7版本 可以安装好 2 找
  • 2023最新C语言经典面试题汇总

    写出Bool int 指针变量 float与 零值 比较的if语句 Bool型 if flag if flag int型 if flag 0 if flag 0 指针变量 if p NULL if p NULL float型 const f
  • [机器学习与scikit-learn-49]:特征工程-特征选择(降维)-4-二级过滤-特征值与标签之间的关系:卡方过滤

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 124073917 目录 前言 第1章
  • android软件开发!Jetpack-MVVM-高频提问和解答,附带学习经验

    感悟 这个世界有一个 二八原则 在好多地方都发挥着作用 在Android开发上我认为也一样有用 做一个Android开发 你也许只会用到Android开发知识中的20 有80 其实你学了也不一定会用 而面试官也一样 他也可能只掌握了20 的
  • java通过JdbcTemplate连接多个(2个以上)不同类型的数据库

    1 业务场景 要求获取不同数据库的表信息和表结构信息 数据库类型包括oracle MySQL SqlServer 2 实现思路 step1 新增数据库连接信息 主机 端口 数据库类型 实例名 用户名 密码 状态 step2 测试连接 成功状
  • Python中常用的设计模式

    主要参考网址 http www pythontip com pythonPatterns 创建型模式 1 抽象工厂模式 class PetShop def init self animal factory None self pet fac