当前位置: 首页 > 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://www.dtcms.com/wzjs/458522.html

相关文章:

  • 网站重新建设的请示百度大数据中心
  • 怎么在网站中做视频背景seo页面代码优化
  • 德庆网站建设深圳网络推广哪家公司好
  • 网站不备案可以使用么国内最新新闻大事
  • 国外免费网站建设免费seo排名优化
  • 做球服的网站有哪些2022世界足球排行榜
  • 网站顶部flash百度网盘人工客服电话
  • logo设计竞标网站百度一下官方网址
  • 锦州做网站公司合肥百度seo排名
  • 义乌做网站zisou8搜狗友链交换
  • 参考网是合法网站吗?今日头条搜索优化
  • 微网站策划方案专业百度seo排名优化
  • 网站的关键词排名怎么做武汉关键词排名工具
  • 郑州建立网站网站seo怎么做
  • 最简单的做网站的软件智能营销系统
  • 营销型网站设计思路贵港seo关键词整站优化
  • 广州做网络服装的网站建设软文营销的优势
  • php网站开发教程培训网店运营怎么学
  • 芜湖住房和城乡建设委员会网站百度资源共享链接分享组
  • 58同城石家庄网站建设谷歌网站优化
  • win7 做网站服务器互联网金融营销案例
  • 天津网站建设zhy88网络推广怎么做效果好
  • 北京城乡建设委员会网站共有产权房优化营商环境工作开展情况汇报
  • 钥匙借用微信小程序免费制作平台长尾词优化外包
  • 英语网站online百度如何做广告
  • 出库入库管理软件app潮州seo建站
  • 南京电商网站开发广州全网推广
  • discuz 手机网站模板长沙网站定制公司
  • lol网站怎么做太原网站建设制作
  • 为什么建设银行网站打不开seo优化一般包括