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

河南建设监理协会网站电话商城和营销型网站建设

河南建设监理协会网站电话,商城和营销型网站建设,wordpress文章发布没有页面模板,网站的站外优化前言: 你是否曾在Python编程中遇到过这样的问题:如何在函数执行后保留局部变量?如何在不修改原函数代码的情况下为其添加新功能?这些问题都可以通过Python中的闭包和装饰器来解决! 本文将带你深入理解Python闭包和装…

前言:

你是否曾在Python编程中遇到过这样的问题:如何在函数执行后保留局部变量?如何在不修改原函数代码的情况下为其添加新功能?这些问题都可以通过Python中的闭包装饰器来解决!

本文将带你深入理解Python闭包和装饰器的核心概念,并通过大量代码示例帮助你掌握这些高级编程技巧。无论你是Python初学者,还是有一定经验的开发者,这篇博客都将为你提供宝贵的学习资源。

你将学到:

  1. 什么是闭包?闭包的构成条件和实际应用。

  2. 装饰器的定义、作用及如何使用装饰器为函数添加新功能。

  3. 如何编写通用装饰器,支持参数传递和返回值处理。

  4. 高级装饰器技巧:类装饰器的使用。

通过本文的学习,你将能够轻松应对Python中的闭包和装饰器问题,提升代码的可维护性和扩展性。快来一起探索Python的高级编程世界吧!

一、闭包

1、为什么要学闭包?

下面将会通过一个例子为你解释学习闭包的重要性:

# 全局作⽤域(全局变量)
num1 = 10
def func():# 局部作⽤域(局部变量)num2 = 20
# 调⽤函数
func()
# 在全局作用域中调用全局变量
print(num1)
# 在全局作⽤域中调⽤局部变量num2
print(num2)

运行结果: 

 通过这个例子,我们发现函数执行结束之后我们并不能够获取函数内部的局部变量。主要原因在于,在Python的底层存在⼀个“垃圾回收机制”,主要的作⽤就是回收内存空间。加快计 算机的运⾏。我们在Python代码中定义的变量也是需要占⽤内存的,所以Python为了回收已经被已经过的内存,会⾃动将函数运⾏以后的内部变量和程序直接回收,这个时候我们就可以通过闭包来解决这种问题了。

2. 什么是闭包?

闭包(Closure)是Python中一个非常重要的概念,尤其是在函数式编程中。简单来说,闭包是指在一个函数内部定义的函数,并且这个内部函数引用了外部函数的变量。闭包的核心作用是保留函数执行时的上下文环境,即使外部函数已经执行完毕,内部函数仍然可以访问外部函数的变量。

3. 闭包的构成条件

闭包的构成需要满足以下三个条件:

  1. 有嵌套:在一个函数内部定义了另一个函数。

  2. 有引用:内部函数引用了外部函数的变量。

  3. 有返回:外部函数返回内部函数的引用(即内部函数的内存地址)。

示例代码:
def outer():num = 20  # 外部函数的局部变量# 嵌套def inner():# 引用print(num)  # 内部函数引用了外部函数的变量# 返回return inner # 实际上inner函数并没有执⾏,只是返回了inner函数在内存中的地址f = outer() # 相当于把inner在内存中的地址赋值给变量f
print(f) #inner函数的内存地址
f() # 找到inner函数的内存地址,并执⾏器内部的代码(num=20),在于闭包函数保留了num=20这个局部变量

运行结果:

在这个例子中,outer 函数内部定义了 inner 函数,并且 inner 函数引用了 outer 函数的局部变量 num。即使 outer 函数执行完毕,inner 函数仍然可以访问 num 变量。

4. 闭包的作用

闭包的主要作用是保留函数执行时的上下文环境。通常情况下,函数执行完毕后,其内部的局部变量会被垃圾回收机制回收。但通过闭包,我们可以保留这些局部变量,使得在全局作用域中仍然可以间接访问它们

5、在闭包的内部实现对外部变量的修改

情景1:直接修改
实例代码:
def outer():count = 0def inner():count = 10print('outer函数中的num:',count)inner()print('outer函数中的num:',count)return innercounter = outer()
print(counter()) #输出None

运行结果:

情景2:使⽤ nonlocal关键字(在函数内部修改函数外部的变量,这个变量⾮全局变量)
实例代码:
def outer():count = 0def inner():nonlocal count #声明count不是局部变量,也不是全局变量,⽽是外部函数outer的局部变量count = 10 # 直接修改outer函数中的count变量print('outer函数中的num:',count)inner()print('outer函数中的num:',count)return innercounter = outer()
print(counter()) #输出None
运行结果:
情景3:使⽤ global关键字(在函数内部声明变量,代表引⽤全局作⽤域中的全局变量)
实例代码:
count = 100
def outer():count = 0def inner():global count # 声明count全局变量,⽽不是外部函数outer的局部变量count = 10 # 直接修改outer函数中的count变量print('outer函数中的num:',count)inner()print('outer函数中的num:',count)return innercounter = outer()
print(counter()) #输出None,函数外部没有count这个变量
print(count) # 外部全局变量的count本来为100被修改为了10

运行结果:

5. 闭包的综合案例

闭包的一个典型应用场景是实现函数调用次数累加器。通过闭包,我们可以在全局作用域中保留计数器的状态。

实例代码:

def outer():count = 0def inner():nonlocal countcount += 1print(count)return innerf = outer()
f() # 输出1
f() # 输出2
f() # 输出3
f() # 输出4

运行结果:

实例代码:

def counter():result = 0def inner(num):nonlocal resultresult += numprint(result)return innerf = counter()
f(1)  # 输出 1
f(2)  # 输出 3
f(3)  # 输出 6

运行结果:

在这个例子中,counter 函数返回了 inner 函数的引用。每次调用 f(num) 时,inner 函数都会修改 result 变量的值,并且这个值会被保留下来。

二、装饰器

1. 什么是装饰器?

装饰器(Decorator)是Python中一种非常强大的工具,它允许我们在不修改原函数代码的情况下,为函数添加新的功能。装饰器的本质是一个闭包函数,它接收一个函数作为参数,并返回一个新的函数。

2. 装饰器的雏形

装饰器的核心思想是:在不改变原函数调用方式的情况下,为函数添加新功能。我们可以通过闭包来实现装饰器。

示例代码:
# 要求:把登录功能封装起来(比如封装成一个函数,添加这个登录不能影响现有功能函数)
'''
装饰器:本质是一个闭包,有嵌套、有引用、有返回(返回的是函数的内存地址)
参数 fn 在 check 中也是一个局部变量
参数 fn:就是要装饰的函数的函数名,如 comment,如 download
'''# 定义装饰器函数 check
def check(fn):def inner():# 开发登录功能print('登录功能')# 调用原函数fn()  # 调用 comment(), download()return inner  # 返回 inner 函数的内存地址# 评论功能(前提:登录)
def comment():print('评论功能')# 使用装饰器 check 装饰 comment 函数
comment = check(comment)  # 调用 check(),把 comment 函数的内存地址赋值给 inner
comment()  # 调用 inner 函数,输出:登录功能 评论功能# 下载功能(前提:登录)
def download():print('下载功能')# 使用装饰器 check 装饰 download 函数
download = check(download)  # 调用 check(),把 download 函数的内存地址赋值给 inner
download()  # 调用 inner 函数,输出:登录功能 下载功能

运行结果:

在这个例子中,check 函数是一个装饰器,它接收一个函数 fn 作为参数,并返回一个新的函数 innerinner 函数首先执行登录功能,然后调用原函数 fn

3. 装饰器的定义

Python提供了 @ 语法糖来简化装饰器的使用。我们可以直接在函数定义前使用 @装饰器名称 来应用装饰器。

示例代码:

def check(fn):def inner():print("登录功能")fn()return inner@check  # 使用装饰器
def comment():print("评论功能")comment()  # 输出:登录功能 评论功能

运行结果:

在这个例子中,@check 语法糖相当于 comment = check(comment),它自动将 comment 函数传递给 check 装饰器。

4. 装饰器的作用:获取程序的执行时间

装饰器的一个常见应用是获取函数的执行时间。我们可以通过装饰器在不修改原函数代码的情况下,为函数添加计时功能。

示例代码:
import timedef get_time(fn):def inner():begin = time.time()fn()end = time.time()print(f"函数执行时间: {end - begin} 秒")return inner@get_time
def demo():for i in range(1000000000):passdemo()  

运行结果:

在这个例子中,get_time 装饰器为 demo 函数添加了计时功能。

5. 带有参数的装饰器

实例代码:

'''
带有参数的装饰器:① 有嵌套 ② 有引用 ③ 有返回
'''# 定义装饰器函数 logging
def logging(fn):def inner(*args, **kwargs):# 添加装饰器代码(输出日志信息)print('-- 日志信息:正在努力计算 --')# 执行要修饰的函数fn(*args, **kwargs)  # 调用 sum_num(a, b)return inner  # 返回 inner 函数的内存地址# 使用装饰器 logging 装饰 sum_num 函数
@logging
def sum_num(*args, **kwargs):result = 0# *args 代表不定长元组参数,args = (10, 20)for i in args:  # i = 10, i = 20result += i# **kwargs 代表不定长字典参数,kwargs = {a:30, b:40}for i in kwargs.values():  # i = 30, i = 40result += iprint(result)  # 输出计算结果# sum_num 带 4 个参数,而且类型不同,10 和 20 以元组形式传递,a=30,b=40 以字典形式传递
sum_num(10, 20, a=30, b=40)

运行结果:

6、带有返回值的装饰器

实例代码:

'''
带有返回值的装饰器:① 有嵌套 ② 有引⽤ ③ 有返回
如果⼀个函数执⾏完毕后,没有return返回值,则默认返回None
'''
def logging(fn):def inner(*args, **kwargs):print('-- ⽇志信息:正在努⼒计算 --')return fn(*args, **kwargs) # fn() = sub_num(20, 10) = resultreturn inner@logging
def sub_num(a, b):result = a - breturn result
print(sub_num(20, 10))

运行结果:

7、通用版本装饰器

为了支持各种类型的函数(无论是否有参数或返回值),我们可以编写一个通用装饰器。通用装饰器可以处理任意数量的参数,并且支持返回值。

示例代码:
def logging(fn):def inner(*args, **kwargs):print("正在执行函数")return fn(*args, **kwargs)return inner@logging
def sum_num(a, b):return a + b@logging
def sub_num(a, b):return a - bprint(sum_num(10, 20))  # 输出:正在执行函数 30
print(sub_num(100, 80))  # 输出:正在执行函数 20

运行结果:

8、装饰器⾼级:使⽤装饰器传递参数

有时候我们需要为装饰器传递参数,以便根据不同的参数执行不同的操作。我们可以通过在装饰器外部再包裹一层函数来实现。

实现代码:

'''
通⽤装饰器:① 有嵌套 ② 有引⽤ ③ 有返回 ④ 有不定⻓参数 ⑤ 有return返回值
真正问题:通过装饰器传递参数,我们应该如何接收这个参数呢?
答:在logging⽅法的外侧在添加⼀个函数,专⻔⽤于接收传递过来的参数
'''
def logging(flag):def decorator(fn):def inner(*args, **kwargs):if flag == '+':print("正在执行加法运算")elif flag == '-':print("正在执行减法运算")return fn(*args, **kwargs)return innerreturn decorator@logging('+')
def sum_num(a, b):return a + b@logging('-')
def sub_num(a, b):return a - bprint(sum_num(10, 20))  # 输出:正在执行加法运算 30
print(sub_num(100, 80))  # 输出:正在执行减法运算 20

运行结果:

1. 装饰器的结构

这个装饰器 logging 是一个带参数的装饰器,它的结构分为三层:

  1. 外层函数 logging(flag)

    • 接收一个参数 flag,用于决定装饰器的行为(比如是加法还是减法)。

    • 返回 decorator 函数。

  2. 中层函数 decorator(fn)

    • 接收一个函数 fn(即被装饰的函数,如 sum_num 或 sub_num)。

    • 返回 inner 函数。

  3. 内层函数 inner(*args, **kwargs)

    • 这是实际执行的函数,它会根据 flag 的值执行不同的逻辑(比如打印“正在执行加法运算”或“正在执行减法运算”)。

    • 最后调用原函数 fn(*args, **kwargs) 并返回其结果。


三、类装饰器

除了函数装饰器,Python还支持类装饰器。类装饰器通过定义一个类来实现装饰器的功能。

示例代码:
class Check:def __init__(self, fn):self.__fn = fndef __call__(self, *args, **kwargs):print("请先登录")self.__fn(*args, **kwargs)@Check
def comment():print("评论功能")comment()  # 输出:请先登录 评论功能

在这个例子中,Check 类是一个类装饰器。它通过 __call__ 方法使得类的实例可以像函数一样被调用。

总结:

通过本文的学习,你应该已经掌握了Python中闭包和装饰器的核心概念和使用方法。闭包和装饰器是Python中非常强大的工具,它们可以帮助你编写更加灵活和可维护的代码。

关键点回顾:

  1. 闭包的核心是保留函数执行时的上下文环境

  2. 装饰器可以在不修改原函数代码的情况下,为函数添加新功能。

  3. 通用装饰器可以处理任意数量的参数,并且支持返回值。

  4. 类装饰器通过 __call__ 方法实现装饰器的功能。

希望这篇博客能够帮助你更好地理解Python中的闭包和装饰器,并在实际项目中灵活运用它们。如果你有任何问题或建议,欢迎在评论区留言!


如果你觉得这篇博客对你有帮助,别忘了点赞、收藏和分享!关注我,获取更多Python编程技巧和高级教程。让我们一起在编程的世界中不断进步!


文章转载自:

http://8Eq840uh.ktnmg.cn
http://jR0RppQ5.ktnmg.cn
http://igdbQCCe.ktnmg.cn
http://CSY13XzS.ktnmg.cn
http://PhVlC5Lh.ktnmg.cn
http://O9Z22xkK.ktnmg.cn
http://CmLJO8HH.ktnmg.cn
http://fO1r3fVc.ktnmg.cn
http://h4NNnF1P.ktnmg.cn
http://roAeEHog.ktnmg.cn
http://CUACWPVa.ktnmg.cn
http://7xJnpUNa.ktnmg.cn
http://cV80ALtc.ktnmg.cn
http://cQERFLur.ktnmg.cn
http://aMIYXb4w.ktnmg.cn
http://3Cbmu4hQ.ktnmg.cn
http://CiBF4YhB.ktnmg.cn
http://cjxPA4yg.ktnmg.cn
http://ifDotCSe.ktnmg.cn
http://wW80Q3zH.ktnmg.cn
http://4NzUkznZ.ktnmg.cn
http://b2UVghto.ktnmg.cn
http://HXhcTFU6.ktnmg.cn
http://p4ksH7WW.ktnmg.cn
http://YscQyXMW.ktnmg.cn
http://deirpM5J.ktnmg.cn
http://ujiZwMkS.ktnmg.cn
http://pOLb0GUM.ktnmg.cn
http://WRNYNFoR.ktnmg.cn
http://vRcLfken.ktnmg.cn
http://www.dtcms.com/wzjs/742071.html

相关文章:

  • 有帮忙做儿童房设计的网站吗资海网络一年做多少网站
  • 用html做网站的心得体会图书馆网站建设请示
  • 营销型网站建设团队网站后端做留言板功能
  • 企业网站建设规划的基本原则是什么公司网站建设的签订合同
  • 出国看病网站开发wordpress西班牙语
  • 东南亚网站建设市场小牛加速器
  • 中国网站制作企业排行榜做信息采集的网站
  • 做一下网站网站服装网站公司网站
  • 网站建设 招标文件秒拍wordpress插件
  • 甘肃省建设厅职业资格注册中心网站做网站比较便宜
  • 企业网站开发韵茵南宁建站官网
  • 网站服务合同模板友情链接检测的特点
  • 青岛定制网站建设连云港网站建设培训
  • 房屋产权地址备案在那个网站做网站建设培训心得
  • 建设银行社保网站网站建设尺寸
  • 钓鱼网站建设信息手机网站模板下载
  • 网站建设方案报价表汉滨网站建设
  • 大型网站开发管发建设网站意义
  • 建瓯市建设局网站怎么做html网站
  • 上海市住房和城乡建设厅网站查询wordpress博客可以下载官方的模板
  • 周口网站建设专家网站建设 蔬菜配送
  • 做采购 通常在什么网站看定制营销的优缺点
  • 网站 风格wordpress 活动 报名 插件
  • 如何优化公司网站wordpress 面向对象
  • 百度网盘官网登陆入口怀化seo网站
  • 网站企业备案和个人备案的区别吗wordpress自动缩略图
  • 成都网站建设公司浅谈wordpress如何开发手机版
  • 网站建设费分多少期摊销白云手机网站开发
  • 栏目手机版 企业网站建筑门户网站
  • 佛山优化网站推广苏州网站建设代理