千家信息网

Python中装饰器语法是怎么样的

发表于:2025-02-23 作者:千家信息网编辑
千家信息网最后更新 2025年02月23日,这篇文章主要介绍了Python中装饰器语法是怎么样的,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Python中装饰器语法详解装饰器是
千家信息网最后更新 2025年02月23日Python中装饰器语法是怎么样的

这篇文章主要介绍了Python中装饰器语法是怎么样的,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

Python中装饰器语法详解

装饰器是python里的一个非常有意思的部分,他用于封装函数代码,显式的将封装器应用到被封装的函数上,从而使得他们选择加入到装饰器指定的功能中。对于在函数运行前处理常见前置条件(例如确认授权),或在函数运行后确保清理(输出清除或异常处理),装饰器都非常有用。

简单来说,装饰器就是实现了一个通用的功能,然后将这个通用的功能应用到不同的、需要使用这个功能的函数上,从而避免每次都在不同函数上反复写相同的功能代码。

装饰器的本质是一个函数,他接受被装饰的函数作为位置参数,装饰器通过使用该参数来执行某些操作,然后返回一个函数引用,这个函数可以是原始函数,或者是另外一个函数。

我们举例子说明,装饰器是这样的函数,他们接受被装饰的可调用函数作为唯一的参数,并且返回一个可调用函数,

registry = []

def register(decorated):

registry.append(decorated)

return decorated

def foo():

return 3

foo = register(foo)

print(registry[0])

register方法是一个简单的装饰器,它把被装饰的函数添加到一个列表中,然后这里是将未改变的被装饰函数返回,可以看出,装饰器一般是传入被装饰函数的引用,然后经过一些指定的处理,最后返回值也是一个函数引用。

还有一种更简单的语法形式:

装饰器的语法糖:我们这里看到的对foo进行装饰的方法是运用

foo = register(foo)语句,还有一种简单的用法是在声明函数的位置应用装饰器,从而使得代码更容易阅读,并且让人立刻意识到使用了装饰器。

registry = []

def register(decorated):

registry.append(decorated)

return decorated

@register

def foo(x=3):

return x

@register

def bar(x=5):

return 5

for func in registry:

print(func())

3

5

再看一个更复杂、更一般化的装饰器函数。装饰器的本质是在执行原有函数(被装饰的函数)的同时,再加上一些额外的功能。

def requires_ints(decorated):

def inner(*args, **kwargs):

kwarg_values = [i for i in kwargs.values()]

for arg in list(args) + kwarg_values:

if not isinstance(arg, int):

raise TypeError('{} only accepts integers as arguments'.format(decorated.__name__))

return decorated(*args, **kwargs)

return inner

在这个装饰器函数requires_ints我们可以看到,他定义了一个内嵌函数inner,这个内嵌函数的参数首先收集被装饰函数的所有参数,然后对其进行判断,判断其是否为整数类型(这就是装饰器添加的额外功能),然后再调用被装饰的函数本身,最后将这个内嵌函数返回。因此当我们再用原函数名进行调用的时候,原来的被装饰函数的引用就能指向这个新的内嵌函数,就能在实现原函数功能的基础上,加上附加的功能了。

同时,我们再提炼一下这里面的几个重难点:

第一,requires_ints中,decorated这个变量是内嵌作用域的变量,在他调用退出后,返回的inner函数是可以记住这个变量的。

第二,python不支持函数的参数列表的多态,即一个函数名只能对应唯一的参数列表形式。

第三,在内嵌函数内部调用被装饰函数的时候,使用了解包参数,关于这args, *kwargs,的参数形式,前面章节中细讲过。

那我们也用这个装饰器来装饰一个函数。

@requires_ints

def foo(x,y):

print(x+y)

foo(3,5)

8

这里将名称foo赋给inner函数,而不是赋给原来被定义的函数,如果运行foo(3,5),将利用传入的这两个参数运行inner函数,inner函数执行类型检查,然后运行被装饰方法,如果传入的不是整形数,例如下面这个例子,那么装饰器的附加功能就会进行类型检查:

@requires_ints

def foo(x,y):

print(x+y)

foo('a',5)

Traceback (most recent call last):

File "E:/12homework/12homework.py", line 15, in

foo('a',5)

File "E:/12homework/12homework.py", line 7, in inner

raise TypeError('{} only accepts integers as arguments'.format(decorated.__name__))

TypeError: foo only accepts integers as arguments

其次内嵌的函数和被装饰的函数的参数形式必须完全一样,这里用的args, *kwargs概况函数参数的一般形式,因此也是完全对应的。

最后说说装饰器参数

最后来介绍这个复杂一些的话题,装饰器参数。之前我们列举的常规例子里,装饰器只有一个参数,就是被装饰的方法。但是,有时让装饰器自身带有一些需要的信息,从而使装饰器可以用恰当的方式装饰方法十分有用。

这些参数并不是和被装饰的函数并列作为参数签名,而是在原有装饰器的基础上额外再增加一层封装,那么,实质是这个接受其他参数的装饰器并不是一个实际的装饰器,而是一个返回装饰器的函数。

最终返回的内嵌函数inner是最终使用indent和sort_keys参数的函数,这没有问题

import json

def json_output(indent=None, sort_keys=False):

def actual_decorator(decorated):

def inner(*args, **kwargs):

result = decorated(*args, **kwargs)

return json.dumps(result, indent=indent, sort_keys=sort_keys)

return inner

return actual_decorator

@json_output(indent=8)

def do_nothing():

return {'status':'done','func':'yes'}

print(do_nothing())

{

"status": "done",

"func": "yes"

}

我们在这里详细解释说明的是操作顺序,看上去我们使用的是@jsonoutput(indent=8),作这和之前的装饰器语法糖看上去有些不同,实际上这个不是最终的装饰器函数,通过调用jsonoutput(indent=8),返回函数指针actual_decorator,这个函数才是真正放在@后的装饰器函数,原始的被装饰函数最终获得了内涵更丰富的inner函数对象,完成了装饰过程,值得一提的是,所谓的装饰器参数最终传给了最内层的inner函数。

记住,在定义装饰器函数后,真正的装饰器函数只有一个参数,那就是被装饰的函数指针,而有其他参数的函数实质上只是装饰器的外围函数,他可以依据参数对装饰器进行进一步的定制。一句话:一个函数不可能接受被装饰的方法,又接受其他参数

在语法糖中@func这种不带括号的,就是直接使用装饰器函数进行装饰,如果是@func()带括号的,实质上是先调用func()函数返回真正的装饰器,然后再用@进行调用。

感谢你能够认真阅读完这篇文章,希望小编分享的"Python中装饰器语法是怎么样的"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!

函数 参数 功能 语法 方法 就是 形式 运行 篇文章 封装 中装 不同 代码 例子 变量 同时 实质 是在 类型 应用 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 绿毒攻速版服务器 临海定制软件开发解决方案 魔兽主宰之剑服务器 企业管理软件开发哪家专业 信息化的快速发展与网络安全 网络安全逆向分析工程师 黑龙江省网络安全知识答案 数据库数据在页面显示乱码 云帮手能导入数据库吗 龙岩网络安全支撑 简答题数据库系统的三级体系结构 公需课网络安全考试答案 大型数据库编程题 中国自研数据库技术再破世界纪录 数据库技术与应用收获 关系数据库的模式灵活 卖服务器赚钱 郑大网络安全研究院 安卓软件开发关于网易云 三国服务器客服人数 网络技术才有智能手机 泰州互联网生物科技有限公司 软件开发每人日价格 常用的数据库或检索系统的对比 数据库数据在页面显示乱码 网络安全九大原则 陕西服务器回收厂家云主机云空间 网络安全法 会议通过 七所大学设置国家网络安全学 国际服选哪个服务器匹配到外国人
0