Python装饰器入门:从闭包到@wraps
2026/6/14 7:35:10 网站建设 项目流程

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("--------结束-------")

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询