在上篇文章中留下了一个问题——装饰器的传参如何实现?其实对于这个问题来说,首先要搞清楚传参的顺序是什么。我们已知的是装饰器的本质就是函数,那么在这嵌套了多层的函数中每一个函数接收的参数是哪一个,作用域哪个范围,这就是实现装饰器传参前需要解决的问题。
一、装饰器传参
在Python中,有时候我们需要给装饰器传递参数来实现更灵活的功能。为了实现装饰器传参,可以使用闭包来定义装饰器。
1.1 传参方式分析
首先来看如上篇文章中的基本装饰器的实现,代码如下:
def login_check(fn):
password = input("请输入密码:")
def inner():
print("密码验证进行中....")
nonlocal password
if password == "123":
print("密码验证成功!")
fn()
else:
print("对不起,密码输入错误!")
return inner
@login_check
def home():
print("欢迎回家!!!")
在本代码中,逻辑其实很简单,就是将函数home
作为参数传递到装饰器login_check
中。如现在需要对回家的人进行记录,那么就需要传递一个参数name
到装饰器中进行使用,按照正常的思路可能会有人会直接在定义装饰器的时候添加形参,但是实际运行的时候结果是如何呢?能成,但也不能成。为什么这么说呢,我们知道装饰器的应用有两种方式,一是直接对装饰器函数进行调用再进一步实现内部函数的调用;二是通过语法糖进行调用。
先说第一种方式,对装饰器函数进行调用,然后将函数home
作为参数传递到装饰器中的fn参数,再传入参数name
到装饰器内部,这样的实现很容易,如下方代码:
def login_check(fn, name):
print(name)
password = input("请输入密码:")
def inner():
print("密码验证进行中....")
nonlocal password
if password == "123":
print("密码验证成功!")
fn()
else:
print("对不起,密码输入错误!")
return inner
def home():
print("欢迎回家!!!")
login_check(home, name='qm')()
这样就实现了装饰器传参,但是大家就忽略了一个问题——代码的美观度。现在是仅仅一个参数,如果参数再多一些呢?再加上此处的应用方式是函数的双双调用,从代码的可维护性来看,后期在维护代码的时候也是比较不方便的,所以这种对于装饰器的传参方式基本上是不会采取的。通常情况下,装饰器的传承是基于语法糖的形式来实现,而语法糖形式实现装饰器传参的话是不能够直接在接收被装饰函数的这一层函数中额外接收装饰器需要的参数的,因此我们需要对装饰器进一步进行嵌套,由这多出来的一层来对额外参数进行接收。
1.2 装饰器传参实现
对装饰器进行调用是必然,调用的时候返回一个内部函数,再由这个内部函数接收被装饰函数作为参数,这样就能成功实现装饰器的传参了,并且完美契合语法糖格式。如下代码(三层嵌套实现装饰器传参):
def people_check(name):
def login_check(fn):
print(name)
password = input("请输入密码:")
def inner():
print("密码验证进行中....")
nonlocal password
if password == "123":
print("密码验证成功!")
fn()
else:
print("对不起,密码输入错误!")
return inner
return login_check
@people_check(name='qm')
def home():
print("欢迎回家!!!")
home()
在上方例子中,函数people_check
接收额外的参数,其是最外部的函数,并返回一个内部函数login_check
,在这里就是装饰器函数,这个函数接收的就是被装饰函数,并再返回一个内部函数inner
,在这个函数中再对被装饰函数进行包装。如此便实现了语法糖实现装饰器的传参了。
二、匿名函数
匿名函数就是没有名称的函数,在Python中通过lambda
关键字来实现,所以又称为lambda函数
。定义的时候并不用def关键字,并且只能包含一个表达式。匿名函数的使用通常是为了简化代码和临时定义简单逻辑的函数。
Python中匿名函数的语法如下:
lambda arguments: expression
其中,arguments
表示函数的参数列表,可以包含零个或多个参数。expression
是一个表达式,表示匿名函数要执行的操作。如下(计算两个数的和):
add = lambda x, y: x + y
result = add(3, 5)
print(result) # 输出:8
在上述代码中,我们使用lambda关键字定义了一个匿名函数add,并将其赋值给变量add。该匿名函数接受两个参数x和y,并返回它们的和。然后我们调用add(3, 5),将结果赋值给变量result,并打印输出结果。
需要注意的是,匿名函数通常用于简单、短小的操作。如果需要定义复杂的逻辑或多行代码,建议使用普通命名函数来提高可读性和维护性。此外,在某些情况下,也可以将匿名函数作为其他函数(如map、filter、sorted等)的参数传递以实现更灵活的功能。例如通过字典的值对字典进行排序,代码如下:
dic = {"小美": 23, "小王": 21, "小明": 18, "小赵": 20}
res = sorted(dic.items(), key=lambda x: x[1])
print(dict(res))
附:下个内容进入到面向对象了,在此之前会先对前面的内容进行一系列的小补充,需要文章中资料的记得联系本人获取!!!