当前位置: 首页 > news >正文

Python中函数的闭包和装饰器

1. python的内部函数示例

# 定义一个外部函数
def func_out(num1):# 定义一个内部函数def func_inner(num2):# 内部函数使用了外部函数的变量(num1)result = num1 + num2print("结果是:", result)# 外部函数返回了内部函数,这里返回的内部函数就是闭包return func_inner# 创建闭包实例,返回内部函数    
# 此时的f是内部函数
f = func_out(100)
# 执行闭包
f(2)
f(3)"""
f接收到func_out的返回值
f = func_inner
f() = func_inner()
"""

示例2:

def config_name(name):def say_hello(info):print(f"{name}: {info}")return say_helloif __name__ == '__main__':# 创建闭包实例tom = config_name("tom")tom("What did you have for lunch ?")jarry = config_name("jarry")jarry("I had vegetables and beef.")"""
tom: What did you have for lunch ?
jarry: I had vegetables and beef.
"""

调用闭包相当于调用内部函数


闭包的构成条件
1. 在函数嵌套的前提下
2. 内部函数使用了外部函数的变量(还包括外部函数的参数)
3. 外部函数返回了内部函数结论:闭包可以对外部函数的变量进行保存

2. 闭包内修改外部变量

def func_out(num1):def func_inner(num2):# 此时的num1属于内部函数,不是外部函数的num1num1 = num2 + 100print("改前:num1 =",num1)# 调用内部函数修改num1的值func_inner(200) # 调用方法改变num1的值print("改后:num1 =",num1)return func_inner
# 实例化闭包
f = func_out(10)"""
改前:num1 = 10
改后:num1 = 10
"""
def func_out(num1):def func_inner(num2):# 此时的num1是外部函数变量nonlocal num1num1 = num2 + 100print("改前:num1 =",num1)# 调用内部函数修改num1的值func_inner(200) # 调用方法改变num1的值print("改后:num1 =",num1)return func_inner
# 实例化闭包
f = func_out(10)
# f(10) --> 这是调用闭包(内部函数),这里没有调用闭包,只是创建了闭包
"""
改前:num1 = 10
改后:num1 = 300
"""

修改闭包使用的外部函数变量使用nonlocal关键字修饰

3. 装饰器:在不改变原有函数的源代码的情况下,给函数添加功能

1.不修改原有函数的源代码
2. 给已有的函数添加额外的功能符合开发中的封闭开放原则
# 1. 定义一个装饰器(一个闭包, 一个内部函数)
def check(fn):# fn是comment函数def inner():print("请先登录")fn()return inner
# 2. 需要被装饰的函数
def comment():print("发表评论")# 3. 使用装饰器装饰函数(增加一个登录功能)
# 左侧的comment函数已经变成了inner()函数
comment = check(comment)
comment()
"""
请先登录
发表评论
"""

装饰器就是把一个函数当作参数传递给闭包中的外部函数,同时在内部函数中使用这个函数,并给它添加新的功能

def check(fn):def inner():print("请先登录")fn()return inner# 解释器遇到@check,会执行comment = check(comment)
@check
def comment():print("发表评论")comment()
"""
请先登录
发表评论
"""

4.修饰带参数的函数

"""装饰带参数的函数"""
def loggin(fn):def inner(a,b):print("请先登录")fn(a,b)return innerdef sum_num(a,b):result = a+bprint(result)# sum_num = inner
sum_num = loggin(sum_num)
sum_num(1,2)
"""
请先登录
3
"""
"""装饰带参数的函数"""
def loggin(fn):def inner(a,b):print("请先登录")fn(a,b)return inner# sum_num = inner, sum_sum = loggin(sum_num)
@loggin
def sum_num(a,b):result = a + bprint(result)sum_num(1,2)
"""
请先登录
3
"""

5. 装饰带有返回值的函数

"""装饰带返回值的函数"""
def loggin(fn):def inner(a,b):print("请先登录")return fn(a,b)return inner@loggin
def sum_num(a,b):result = a+breturn resultans = sum_num(1,2)
print("ans = ",ans)
"""
请先登录
ans =  3
"""

6. 修饰不定长参数的函数

def loggin(fn):def inner(*args):print("请先登录")return fn(*args)return inner@loggin
def sum_args(*args):ans = sum(args)return ansans = sum_args(1,2,3,4,5)
print("ans = ",ans)
"""
请先登录
ans =  15
"""

7. 多个装饰器的使用

def check1(fn):def inner1():print("登录验证1")fn()return inner1def check2(fn):def inner2():print("登录验证2")fn()return inner2@check2
@check1
def comment():print("发表评论")comment()
"""
登录验证2
登录验证1
发表评论
"""

8. 带有参数的装饰器

"""
带参数的装饰器,正确案例
"""
def loggin(flag):def decorator(fn):def inner(num1, num2):# 判断流程if flag == "+":print("--正在努力加法计算--")elif flag == "-":print("--正在努力减法计算--")ant = fn (num1,num2)return antreturn innerreturn decorator# 被带有参数的装饰器饰的函数
@loggin("+")  # 1. loggin("+")  2. @decorator起到装饰器的功能了
def sum_num(a, b):res = a + breturn resresult = sum_num(1,3)
print("result = ",result)
带参数的装饰器
1. 装饰器的外部函数只接受一个参数 -- 被装饰的函数
2. 需要给装饰器参数需要在装饰器外部再增加一个函数

9. call方法

class Check(object):def __call__(self,*args,**kwargs):print("请先登录")c1 = Check()
c1()
"""请先登录"""

10. 类装饰器

class Check(object):def __init__(self,fn):self._fn = fndef __call__(self,*args,**kwargs):print("请先登录")self._fn()@Check   # comment = Check(comment)
def comment():print("发表评论")comment()
"""
请先登录
发表评论
"""

11. property 装饰器方式

class Person(object):def __init__(self) -> None:self.__age = 0@propertydef age(self):return self.__age@age.setterdef age(self, new_age):self.__age = new_agep = Person()
print(p.age)p.age = 100
print(p.age)

12. property类属性方式

class Person(object) : def __init__(self) -> None:self.__age = 0def get_age(self):return self.__agedef set_age(self, new_age):if new_age >= 150:print("年龄错误")else:self.__age = new_ageage = property(get_age, set_age)p = Person()
print(p.age)p.age = 60
print( p.age )

http://www.xdnf.cn/news/1370683.html

相关文章:

  • 读懂支持向量机(SVM)
  • C++ STL 顶层设计与安全:迭代器、失效与线程安全
  • 【Python实战练习】用 Python与Pygame 打造完整的贪吃蛇小游戏
  • 懂支持向量机(SVM):从原理到实战拆解
  • 机器学习模型可解释库的介绍:Shapash (一)
  • 深度学习(五):正则化:约束模型的复杂度
  • Python 全局变量使用
  • 声明式微服务通信新范式:OpenFeign如何简化RestTemplate调用
  • 乳腺癌数据集支持向量机实践学习总结
  • `stat` 系统调用详解
  • AI应用--接口测试篇
  • 实训日志day28
  • Elasticsearch中的设置refresh_interval
  • 文献阅读笔记【雷达辐射源识别】:Recognition of Unknown Radar Emitters with Machine Learning
  • 浅谈ArrayList的扩容机制
  • Nginx配置学习及多应用场景配置示例
  • 验证码请求与缓存问题解决方案
  • Leetcode—1163. 按字典序排在最后的子串【困难】
  • 智慧园区:从技术赋能到价值重构,解锁园区运营新范式
  • 产品经理成长手册(2)——产品文档能力
  • 二、JVM 入门——(三)栈
  • 两数之和,leetCode热题100,C++实现
  • 链改2.0六方会谈协同创新—可信资产IPO与数链金融RWA双轮驱动
  • 第17章|PowerShell 安全警报——高分学习笔记(运维实战向)
  • 使用Kiro智能开发PYTHON应用程序
  • onnx入门教程(五)——实现 PyTorch-ONNX 精度对齐工具
  • Ubuntu操作系统下MySQL、MongoDB、Redis
  • 基于 LQG 控制的轨迹跟踪 —— 从原理到实践
  • 优雅草黑曼巴知识付费项目交付顺带:深入剖析 WebApp 的封装原理与实践-卓伊凡
  • MD5校验算法