Python笔记11-闭包、装饰器和设计模式

文章目录

闭包

在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。

示例

css 复制代码
def outer(logo):
    def inner(msg):
        #logo="<"+logo+">"  会报错 表示不认识 logo
        nonlocal logo  #如果要修改 外部函数的值必须使用nonlocal修饰
        logo="<"+logo+">"
        #print(f"<{logo}>{msg}<{logo}>")
        print(f"{logo}{msg}{logo}")
    return inner

fn=outer("mytest")
fn("你好")  #<mytest>你好<mytest>

需要使用nonlocal关键字修饰外部函数的变量才可在内部函数中修改它

优点,使用闭包可以让我们得到:

无需定义全局变量即可实现通过函数,持续的访问、修改某个值

闭包使用的变量的所用于在函数内,难以被错误的调用修改

缺点:

由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放,一直占用内存

装饰器

装饰器其实也是一种闭包, 其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能

如我们希望给sleep函数,增加一个功能:

在调用sleep前输出:我要睡觉了

在调用sleep后输出:我起床了

css 复制代码
def sleep():
    import random
    import time
    print("睡眠中.....")
    time.sleep(random.randint(1,3))
sleep()

可以借助闭包的功能

定义一个闭包函数, 在闭包函数内部:

执行目标函数

同时添加想要的功能

css 复制代码
def sleep():
    import random
    import time
    print("睡眠中.....")
    time.sleep(random.randint(1,3))

def outer(func):
    def inner():
        #print(f"<{logo}>{msg}<{logo}>")
        print(f"我要睡觉了...")
        func()
        print(f"我要起床了...")
    return inner

fn = outer(sleep)
fn()

装饰器的语法糖:可以使用注解的方式来使用闭包

css 复制代码
def outer2(func):
    def inner2():
        #print(f"<{logo}>{msg}<{logo}>")
        print(f"我要睡觉了...")
        func()
        print(f"我要起床了...")
    return inner2
@outer2   # 增加注解
def sleep():
    import random
    import time
    print("睡眠中.....")
    time.sleep(random.randint(1,3))
sleep()

设计模式

设计模式是一种编程套路,可以极大的方便程序的开发。

最常见、最经典的设计模式,就是我们所学习的面向对象了。

除了面向对象外,在编程中也有很多既定的套路可以方便开发,我们称之为设计模式:

单例、工厂模式、 建造者、责任链、状态、备忘录、解释器、访问者、观察者、中介、模板、代理模式等等模式

这里我挑选了2个经常用到的单例、工厂模式进行了解。

单例模式

某些场景下, 我们需要一个类无论获取多少次类对象,都仅仅提供一个具体的实例

用以节省创建类对象的开销和内存开销

比如某些工具类,仅需要1个实例,即可在各处使用,这就是单例模式所要实现的效果

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。

在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

定义: 保证一个类只有一个实例,并提供一个访问它的全局访问点

适用场景:当一个类只能有一个实例,而客户可以从一个众所周知的访问点访问它时。

实现方式:

1.在一个文件中定义类并创建对象

css 复制代码
class StrUtil:
    pass

str_util = StrUtil()

2.另一个文件中直接导入对象使用

css 复制代码
from imp_file import str_util
sutil1 = str_util
sutil2 = str_util
print(sutil2)#<imp_file.StrUtil object at 0x000001A13030A050>
print(sutil1)#<imp_file.StrUtil object at 0x000001A13030A050>

工厂模式

当需要大量创建一个类的实例的时候, 可以使用工厂模式。

即,基于工厂提供的方法去创建对象,可以太容易控制对象创建逻辑。

一般情况下创建对象:

css 复制代码
class Person:
    pass
class Worker(Person):
    pass
class Student(Person):
    pass
class Teacher(Person):
    pass
worker = Worker()
stu = Student()
teacher = Teacher()

工厂模式创建对象:

css 复制代码
class Person:
	pass
class Worker(Person):
	pass
class Student(Person):
	pass
class Teacher(Person):
	pass
class Factory:
    def get_person(self,p_type):
        if p_type=='w':
            return Worker()
        if p_type=='s':
            return Student()
        else:
            return Teacher()

factory = Factory()
worker = factory.get_person('w' )
stu = factory.get_person('s')
teacher = factory.get_person('t')

使用工厂类的get_person()方法去创建具体的类对象

优点:

大批量创建对象的时候有统一的入口,易于代码维护,当需要修改创建逻辑时,仅修改工厂类的创建方法即可

符合现实世界的模式,即由工厂来制作产品(对象)

相关推荐
BU摆烂会噶5 分钟前
【LangGraph】持久化实现的三大能力——时间旅行
数据库·人工智能·python·postgresql·langchain
消失的旧时光-19431 小时前
统一并发模型:线程、Reactor、协程本质是一件事(从线程到协程 · 第6篇·终章)
java·python·算法
zhaoyong2223 小时前
MySQL 存储过程中字符集与排序规则不匹配导致查询性能下降的解决方案
jvm·数据库·python
sinat_383437363 小时前
golang如何从Python转型Go开发_golang从Python转型Go开发攻略
jvm·数据库·python
rockey6273 小时前
基于AScript的python3脚本语言发布啦!
python·c#·.net·script·python3·eval·expression·function·动态脚本
gqk013 小时前
Python入门
python
Muyuan19984 小时前
28.Paper RAG Agent 开发记录:修复 LLM Rerank 的解析、Fallback 与可验证性
linux·人工智能·windows·python·django·fastapi
代码小书生4 小时前
statistics,一个统计的 Python 库!
开发语言·python
STLearner4 小时前
SIGIR 2026 | LLM × Graph论文总结(图增强LLM,GraphRAG,Agent,多模态,知识图谱,搜索,推
人工智能·python·深度学习·神经网络·机器学习·数据挖掘·知识图谱
FreakStudio4 小时前
MicroPython 内核开发者直接狂喜!这个 Claude 插件市场,把开发全流程做成了「对话式外挂」
python·单片机·嵌入式·面向对象·并行计算·电子diy