news 2026/7/7 21:33:15

Python装饰器入门:从闭包到@wraps

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python装饰器入门:从闭包到@wraps

Python学习笔记-Day9-装饰器篇

函数的使用

首先回顾一下前面学过的函数:

def hi(name='yasoob'): return 'hi ' + name greet = hi print(greet())

在python中,一切皆对象

在函数里定义函数

#方法一、 def a(name = 'youzi'): print('youzi') def greet(): return 'now greet() function' def welcome(): return 'now welcome() function' print(greet()) print(welcome()) print('now a() function') hi() #方法二、 #这里如果也可以写成: def a(name='youzi'): def greet(): return 'now greet() function' def welcome(): return 'now welcome() function' if name == 'youzi': return greet else: return welcome num = a(name='ddd') num1 = a(name='youzi') print(num()) print(num1())

这里解释方法二细节:

  1. name='youzi’是默认参数,当不填的时候,就是youzi
  2. retrun greet:这里greet是对象,当加上括号,就调用执行了这个函数
  3. num = a(name=‘ddd’):实例化a,然后传入参数ddd,并赋值给num,然后再通过判断传入的值来,返回相应的值
  4. 其实如果当函数不加括号,就可以到处传递,并且可以赋值给别的变量,而不去执行它。!!!
  5. 这里其实我们如果调用函数,不传参的话,默认就是youzi,然后就会返回greet,这个时候我们可以这么写,a()(),就是调用greet
  6. 当我把num = a(name=‘zhangsan’),那么就会返回welcome函数

重要点

函数里面的函数,如果没有调用就不会被执行,只有调用的时候才会执行
函数里面的函数只能在函数里面的函数调用,不能在函数的外部调用
从函数中返回函数,其实就是调用函数
变量也可以接收函数,但是函数一般分别两种,一种是带括号的叫调用函数并且执行,另一种是不带括号的叫对象

#定义一个函数名叫hi def hi(): #返回的是hi yasoob return 'hi yasoob' #定义一个函数,但是因为我们今天要讲的是装饰器,所以func这个的作用其实是用来接收函数的,当然也可以接收变量、字典、列表参数等 def doSomethingBeforeHi(func): print('I am doing some boring work before executing hi()') a = func() #这个其实是调用我们传过来的函数,因为加了括号 print(a) doSomethingBeforeHi(hi)

函数里定义函数,然后在函数里调用函数

双层嵌套函数,并且调用另一个函数

def a_new_decorator(a_func): def wrapTheFunction(): print("I am doing some boring work before executing a_func()") #调用传递过来的函数 a_func() print("I am doing some boring work after executing a_func()") #这个return的作用在于触发函数,并且调用函数 return wrapTheFunction def a_function_requiring_decoration(): print("I am the function which needs some decoration to remove my foul smell") a_function_requiring_decoration() #print(a_new_decorator(a_function_requiring_decoration)) a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration) a_function_requiring_decoration()

总结:

可以函数里面定义函数,当然也可以相互传递函数,函数的参数也可以接收函数

接下来,开始进装饰器,这个时候讲装饰器就会好理解点,博客当时学这个也是很头大,不知道为什么这样做?后面发现之后,感觉还挺有意思的

@符号来使用装饰器

这里先提前解释:
在装饰函数的时候,其实就已经做了一个动作,就是把下面的函数名,传给了装饰的函数(定义的装饰函数),如果不理解接着往下看

演示

def a_new_decorator(a_func): def wrapTheFunction(): print("I am doing some boring work before executing a_func()") a_func() print("I am doing some boring work after executing a_func()") return wrapTheFunction @a_new_decorator def a_function_requiring_decoration(): print("I am the function which needs some decoration to remove my foul smell") #把a_function_requiring_decoration放到a_new_decorator装饰,但是装饰不会调用 a_new_decorator(a_function_requiring_decoration) a_function_requiring_decoration()
def a_new_decorator(a_func): def wrapTheFunction(): print("I am doing some boring work before executing a_func()") a_func() print("I am doing some boring work after executing a_func()") return wrapTheFunction @a_new_decorator def a_function_requiring_decoration(): print("I am the function which needs some decoration to remove my foul smell") print(a_function_requiring_decoration.__name__) >>wrapTheFunction 封装函数 >>这里我们想打印原函数的名字,所以接下来我们需要使用@wraps

使用wraps来保持原函数的名字

#从functools库导入函数 from functools import wraps #定义一个函数,添加一个参数f,用来接收函数 def decorator_name(f): #让原函数保持不变 @wraps(f) #这个是语法规范,参数是固定死的,函数名不是,可以随便改,但是要符合命名规范 def decorated(*args,**kwargs): #判断can_run,如果是True就不执行,是false就执行 if not can_run: return "Functions will not run" #把原函数的参数和输入的内容都返回回去 return f(*args,**kwargs) #返回decorated,作用是调用并执行函数 return decorated #使用装饰器 @decorator_name def func(): return ("Functions is running") can_run = True print(func()) can_run = False print(func())

return func(*args,**kwargs) 的核心作用:
动态调用函数:func可以是任何函数
传递所有参数:*args传递所有位置参数,也就是元组,**kwargs传递所有关键字参数,也就是字典
保持透明性:装饰器不需要知道被装饰函数的具体函数
返回结果:将原始函数的返回值原样返回

闭包

再说一个知识点,那就是闭包

解释:通俗来说,闭包就是函数及其周边环境的组合。(在本文语境下,你可以暂时理解周边环境就是一些外部的变量)

闭包通常涉及到一个内部函数,内部函数可以访问或者说记住外部函数的局部变量,即使外部函数已经执行完毕。

代码如下:

# 创建一个装饰器,名为simple_decorator,里面func可以理解为参数也是函数 def simple_decorator(func): def wrapper(): print("--------开始-------") func() print("--------结束-------") #触发wrapper,也就是调用该函数 return wrapper def greet(): print("您好!") closure = simple_decorator(greet) print(type(closure))

closure就是一个闭包的案例!

print("--------开始-------") func() print("--------结束-------") 本质上执行的函数代码 print("--------开始-------") greet() print("--------结束-------")
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/5 13:51:02

基于springboot的实习管理系统毕业论文+PPT(附源代码+演示视频)

文章目录基于springboot的实习管理系统一、项目简介(源代码在文末)1.运行视频2.🚀 项目技术栈3.✅ 环境要求说明4.包含的文件列表(含论文)前台运行截图后台运行截图项目部署源码下载基于springboot的实习管理系统 如需…

作者头像 李华
网站建设 2026/7/6 15:45:54

Hmsc建模实战:环境、系统发育与种间关联的综合考量

生态学家们一直在寻找更好的方法来研究多个物种如何在环境中共同生存。联合物种分布模型(JSDM)就是这样一个强大的新工具,它让我们能同时分析整个物种群落的分布规律。其中,一个名为Hmsc的R语言程序包受到了广泛关注。这个模型就像…

作者头像 李华
网站建设 2026/7/4 16:22:26

少儿编程Scratch3.0教程——02动作积木(基础知识)

在 少儿编程Scratch3.0教程——01初识Scratch 中我已经将Scratch软件的各个组成部分都简单的介绍了一下,接下来就会分不同的文章来详细介绍九种不同类型的积木,每种积木类型我都会分成两遍文章,第一篇是基础知识,是来说明每个积木…

作者头像 李华