最新要闻
- 便利仔便利店的加盟条件有哪些?
- 贾跃亭的「前搭档」,拿下了400亿投资 世界今日讯
- 陆金所理财可靠吗最新_陆金所理财可靠 环球微资讯
- 明确164项重点工作,商务部印发《自贸试验区重点工作清单(2023—2025年)》 全球微速讯
- 天天微动态丨基于千兆光网和MEC边缘计算 ,实现“云-网-端”融合协同的智慧工厂创新组网设计
- 长三角铁路端午小长假三天发送旅客超900万人次|环球速看
- 全球最大、海拔最高“水光互补”电站投产
- 活得明白,爱得清醒 全球今日报
- 端午盐城文旅市场异彩纷呈
- 开“套牌车”还是无证驾驶!交警:罚你没商量 全球要闻
- 暴风控股及冯鑫被列为“老赖”
- 全球观热点:端午假期出行订单涨幅近60% 有人打顺风车跑了995公里
- 今日快讯:北京690分学霸采访中接到清华电话 父子笑成花:那就清华呗
- 广东一蔚来换电站发生起火 蔚来客服:换电站正常可以保证安全
- 厂商回应RTX 4060 Ti/RX 7600破发降价:卖不动 保销量|世界看热讯
- RTX 4060 3DMark跑分大量泄露:对比RTX 3060 8GB提升近50%
手机
2023年甘肃高考成绩今日公布 高考志愿填报6月27日开始
【环球新视野】分享家常卤鸡肉的简单方法
- 2023年甘肃高考成绩今日公布 高考志愿填报6月27日开始
- 【环球新视野】分享家常卤鸡肉的简单方法
- 佳能23年Q4推重磅相机EOS R1 天天播资讯
- 环球快消息!再熬77天,四大生肖天赐福气,福禄齐全,内心强大
- 高速球机是什么一体的_高速球HTDF718R
- 邮储银行白银市分行举办“浓情端午 粽享邮储”活动
家电
当前聚焦:python测试开发面试常考题:装饰器
简介
Python 装饰器是一个可调用的(函数、方法或类),它获得一个函数对象 func_in 作为输入,并返回另一函数对象 func_out。它用于扩展函数、方法或类的行为。
装饰器模式通常用于扩展对象的功能。在日常生活中,这种扩展的例子有:在枪上加一个消音器,使用不同的相机镜头等等。
(资料图片仅供参考)
Django框架中有大量装饰器
- 限制某些HTTP请求对视图的访问
- 控制
- 按单个视图控制压缩
- 基于特定HTTP请求头控制缓存
Pyramid框架和Zope应用服务器也使用装饰器来实现各种目标。
- 将函数注册为事件订阅者
- 以特定权限保护一个方法
- 实现适配器模式
应用
装饰器模式在跨领域方面大放异彩:
- 数据验证
- 缓存
- 日志
- 监控
- 调试
- 业务规则
- 加密
使用修饰器模式的另一个常见例子是(Graphical User Interface,GUI)工具集。在GUI工具集中,我们希望能够将一些特性,比如边框、阴影、颜色以及滚屏,添加到组件/控件。
第一类对象
装饰器是Python中非常强大和有用的工具,它允许程序员修改函数或类的行为。装饰器允许我们封装另一个函数,以扩展被封装函数的行为,而不需要修改它。但在深入研究装饰器之前,让我们先了解一些概念,这些概念在学习装饰器时将会很有用。
在Python中,函数是第一类对象,这意味着 Python 中的函数可以作为参数使用或传递。
第一类函数的属性:
- 函数是对象类型的实例
- 可以将函数存储在变量
- 可以将函数作为参数传递给其他函数
- 可以从函数中返回函数。
- 可以将它们存储在数据结构中,如哈希表、列表、...
例1:将函数视为对象。
def shout(text): return text.upper() print(shout("Hello")) yell = shout print(yell("Hello"))
输出:
HELLOHELLO
例2:将函数作为参数传递
def shout(text): return text.upper() def whisper(text): return text.lower() def greet(func): # storing the function in a variable greeting = func("""Hi, I am created by a function passed as an argument.""") print (greeting) greet(shout)greet(whisper)
输出:
HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT.hi, i am created by a function passed as an argument.
例3: 从函数中返回函数。
def shout(text): return text.upper() def whisper(text): return text.lower() def greet(func): # storing the function in a variable greeting = func("""Hi, I am created by a function passed as an argument.""") print (greeting) greet(shout)greet(whisper)
输出:
25
参考资料
本文涉及的python中文资源 请在github上点赞,谢谢!
本文相关书籍下载
https://www.geeksforgeeks.org/decorators-in-python/
https://realpython.com/primer-on-python-decorators/
装饰器
如上所述,装饰器是用来修改函数或类的行为的。在装饰器中,函数被当作函数的参数,然后在封装函数中调用。
- 装饰器的语法:
@gfg_decoratordef hello_decorator(): print("Gfg")"""Above code is equivalent to -def hello_decorator(): print("Gfg") hello_decorator = gfg_decorator(hello_decorator)"""
gfg_decorator 是一个可调用的函数,它将在另一个可调用的函数hello_decorator函数上面添加一些代码,并返回封装函数。
- 装饰器可以修改行为:
# defining a decoratordef hello_decorator(func): # inner1 is a Wrapper function in # which the argument is called # inner function can access the outer local # functions like in this case "func" def inner1(): print("Hello, this is before function execution") # calling the actual function now # inside the wrapper function. func() print("This is after function execution") return inner1 # defining a function, to be called inside wrapperdef function_to_be_used(): print("This is inside the function !!") # passing "function_to_be_used" inside the# decorator to control its behaviourfunction_to_be_used = hello_decorator(function_to_be_used) # calling the functionfunction_to_be_used()
输出:
Hello, this is before function executionThis is inside the function !!This is after function execution
让我们跳到另一个例子,在这个例子中,我们可以用装饰器轻松地找出函数的执行时间。
import timeimport mathimport functools # decorator to calculate duration# taken by any function.def calculate_time(func): # added arguments inside the inner1, # if function takes any arguments, # can be added like this. @functools.wraps(func) # 支持内省,一般可以不用,多用于文档 def inner1(*args, **kwargs): # storing time before function execution begin = time.time() func(*args, **kwargs) # storing time after function execution end = time.time() print("Total time taken in : ", func.__name__, end - begin) return inner1 # this can be added to any function present,# in this case to calculate a factorial@calculate_timedef factorial(num): # sleep 2 seconds because it takes very less time # so that you can see the actual difference time.sleep(2) print(math.factorial(num)) # calling the function.factorial(10)
@functools.wraps装饰器使用函数functools.update_wrapper()来更新特殊属性,如__name__和__doc__,这些属性在自省中使用。
输出:
3628800Total time taken in : factorial 2.0061802864074707
- 如果函数有返回或有参数传递给函数,怎么办?
在上面所有的例子中,函数都没有返回任何东西,所以没有问题,但人们可能需要返回的值。
def hello_decorator(func): def inner1(*args, **kwargs): print("before Execution") # getting the returned value returned_value = func(*args, **kwargs) print("after Execution") # returning the value to the original frame return returned_value return inner1 # adding decorator to the function@hello_decoratordef sum_two_numbers(a, b): print("Inside the function") return a + b a, b = 1, 2 # getting the value through return of the functionprint("Sum =", sum_two_numbers(a, b))
输出:
before ExecutionInside the functionafter ExecutionSum = 3
内部函数接收的参数是*args和**kwargs,这意味着可以传递任何长度的位置参数的元组或关键字参数的字典。这使得它成为通用的装饰器,可以装饰具有任何数量参数的函数。
- 链式装饰器
链式装饰器是指用多个装饰器来装饰函数。
# code for testing decorator chainingdef decor1(func): def inner(): x = func() return x * x return inner def decor(func): def inner(): x = func() return 2 * x return inner @decor1@decordef num(): return 10 @decor@decor1def num2(): return 10 print(num())print(num2())
输出
400200
上面的例子类似于调用函数---
decor1(decor(num))decor(decor1(num2))
一些常用的装饰器在 Python 中甚至是内建的,它们是 @classmethod, @staticmethod, 和 @property。@classmethod 和 @staticmethod 装饰器用于定义类命名空间中的方法,这些方法与该类的特定实例没有关系。@property装饰器是用来定制类属性的getters和setters的。
- 类装饰器
在 Python 3.7 中的新的 dataclasses 模块中完成:
from decorators import debug, do_twice@debug@do_twicedef greet(name): print(f"Hello {name}")
语法的含义与函数装饰器相似。你可以通过写PlayingCard = dataclass(PlayingCard)来进行装饰。
类装饰器的一个常见用途是作为元类的一些使用情况的更简单的替代。
编写一个类装饰器与编写一个函数装饰器非常相似。唯一的区别是,装饰器将接收类而不是函数作为参数。事实上,你在上面看到的所有装饰器都可以作为类装饰器工作。
- 带参数与不带参数的装饰器
def repeat(_func=None, *, num_times=2): def decorator_repeat(func): @functools.wraps(func) def wrapper_repeat(*args, **kwargs): for _ in range(num_times): value = func(*args, **kwargs) return value return wrapper_repeat if _func is None: return decorator_repeat else: return decorator_repeat(_func)
使用functools.partial也可达到类似效果。
以下是slowdown的演进版本
import functoolsimport timedef slow_down(_func=None, *, rate=1): """Sleep given amount of seconds before calling the function""" def decorator_slow_down(func): @functools.wraps(func) def wrapper_slow_down(*args, **kwargs): time.sleep(rate) return func(*args, **kwargs) return wrapper_slow_down if _func is None: return decorator_slow_down else: return decorator_slow_down(_func)
- 有状态的装饰器
import functoolsdef count_calls(func): @functools.wraps(func) def wrapper_count_calls(*args, **kwargs): wrapper_count_calls.num_calls += 1 print(f"Call {wrapper_count_calls.num_calls} of {func.__name__!r}") return func(*args, **kwargs) wrapper_count_calls.num_calls = 0 return wrapper_count_calls@count_callsdef say_whee(): print("Whee!")
对函数的调用次数--存储在包装函数的函数属性 .num_calls 中。下面是使用它的效果:
>>> say_whee()Call 1 of "say_whee"Whee!>>> say_whee()Call 2 of "say_whee"Whee!>>> say_whee.num_calls2
维护状态的典型方法是使用类装饰器。
import functoolsclass CountCalls: def __init__(self, func): functools.update_wrapper(self, func) self.func = func self.num_calls = 0 def __call__(self, *args, **kwargs): self.num_calls += 1 print(f"Call {self.num_calls} of {self.func.__name__!r}") return self.func(*args, **kwargs)@CountCallsdef say_whee(): print("Whee!")
- 单例模式
单例是只有一个实例的类。比如 None、True 和 False,可以使用 is 关键字来比较 None。
import functoolsdef singleton(cls): """Make a class a Singleton class (only one instance)""" @functools.wraps(cls) def wrapper_singleton(*args, **kwargs): if not wrapper_singleton.instance: wrapper_singleton.instance = cls(*args, **kwargs) return wrapper_singleton.instance wrapper_singleton.instance = None return wrapper_singleton@singletonclass TheOne: pass
如你所见,这个类装饰器与我们的函数装饰器遵循相同的模板。唯一的区别是,我们使用 cls 而不是 func 作为参数名,以表明它是类装饰器。
让我们看看它是否有效:
>>> first_one = TheOne()>>> another_one = TheOne()>>> id(first_one)140094218762280>>> id(another_one)140094218762280>>> first_one is another_oneTrue
注意:在Python中,单例其实并不像其他语言那样经常使用,通常用全局变量来实现更好。
- 缓存返回值
装饰器可以为缓存和备忘提供一个很好的机制。作为一个例子,让我们看一下斐波那契数列的递归定义:
import functoolsfrom decorators import count_callsdef cache(func): """Keep a cache of previous function calls""" @functools.wraps(func) def wrapper_cache(*args, **kwargs): cache_key = args + tuple(kwargs.items()) if cache_key not in wrapper_cache.cache: wrapper_cache.cache[cache_key] = func(*args, **kwargs) return wrapper_cache.cache[cache_key] wrapper_cache.cache = dict() return wrapper_cache@cache@count_callsdef fibonacci(num): if num < 2: return num return fibonacci(num - 1) + fibonacci(num - 2)
在标准库中,最近使用最少的缓存(LRU)可作为 @functools.lru_cache。
这个装饰器比你上面看到的那个有更多的功能。你应该使用@functools.lru_cache而不是写你自己的缓存装饰器:
import functools@functools.lru_cache(maxsize=4)def fibonacci(num): print(f"Calculating fibonacci({num})") if num < 2: return num return fibonacci(num - 1) + fibonacci(num - 2)
maxsize参数指定了多少个最近的调用被缓存。默认值是128,但你可以指定maxsize=None来缓存所有函数调用。然而,要注意的是,如果你要缓存许多大的对象,这可能会导致内存问题。
描述器descriptor
任何定义了__get__()
,__set__()
或__delete__()
方法的对象。当类属性为描述器时,它的特殊绑定行为就会在属性查找时被触发。通常情况下,使用a.b来获取、设置或删除属性时会在a的类字典中查找名称为b的对象,但如果b是描述器,则会调用对应的描述器方法。理解描述器的概念是更深层次理解 Python 的关键,因为这是许多重要特性的基础,包括函数、方法、属性、类方法、静态方法以及对超类的引用等等。
有关描述符的方法的详情可参看实现描述器。
class property(fget=None, fset=None, fdel=None, doc=None)
fget 是获取属性值的函数。 fset 是用于设置属性值的函数。 fdel 是用于删除属性值的函数。并且 doc 为属性对象创建文档字符串。
class C(): def __init__(self): self._x = None def getx(self): return self._x def setx(self, value): self._x = value def delx(self): del self._x x = property(getx, setx, delx, "I"m the "x" property.") demo = C()demo.x = 5print(demo.x)print(demo.getx())
执行结果
55
更快捷的方式:
class C(): def __init__(self): self._x = None @property def x(self): """I"m the "x" property.""" return self._x @x.setter def x(self, value): self._x = value @x.deleter def x(self): del self._x demo = C()demo.x = 5print(demo.x)
@property 装饰器会将 x() 方法转化为同名的只读属性的 "getter",并将 x的文档字符串设置为 "I"m the "x" property."
执行结果
5
关键词:
当前聚焦:python测试开发面试常考题:装饰器
“美国最危险的人”,离世!_当前看点
暗黑破坏神4暗金装备快速获取攻略分享|世界热消息
《暗黑破坏神4》冰霜氏族勇者怎么打?冰霜氏族勇者攻略
即时焦点:EmbracerGroup以惊人的低价购买了指环王的版权
当前滚动:谷歌Pixel平板电脑天气体验即将登陆更多设备
东风集团回购股票权险些被少数股东剥夺|汽势观察 环球热头条
仓鼠多少钱一只萌宠乐园(仓鼠多少钱一只)
光峰科技(688007.SH):研发制备的荧光轮技术在发光效率、发光亮度、稳定性、可靠性等方面,均处于全球领先的水平|世界热点评
今日快讯:免费领!Epic游戏商店领取两款游戏
26-28日降水减弱 气温上升
聚焦幼儿“三性” 创设互动环境
拒绝域怎么求-拒绝域
备孕喝豆浆有什么好处_怀孕可以喝豆奶吗 世界聚焦
迪士尼下雨天有花车巡游吗 天天最资讯
便利仔便利店的加盟条件有哪些?
TikTok在韩国崛起 挑战传统社交媒体 环球即时看
马斯克回应约架扎克伯格:可能真要打了 不打无准备之仗
全球动态:“寄啸山庄”这样“寄啸于心”何园推出主题夜演
2023年河北高考成绩查询方式
郭珍霓:眼角眉梢皆风情,媚骨天成“剧抛脸”,为何不火
让人羡慕的“姐弟恋”夫妻,全都抱起金砖,唯独他俩差一轮仍恩爱-当前热讯
天天滚动:“科中深化务实合作的新见证”
微视频|大地诗篇|世界微速讯
1/10盎司本色生肖银币价格(2023年06月25日)_天天微头条
河南省历年高考一分一段表汇总(2018-2023)
2023天津户籍购房政策一览|天天实时
第三届长三角体育节残健融合定向赛湖州举行|环球快资讯
关于龙凤胎高考成绩都600分以上相差1分及龙凤胎高考成绩都600分以上相差1分详情
重点聚焦!2023深圳市中考时间安排
从水产养殖专业研究生到中福会幼儿园教师,这个跨界男生如何打破专业边界? 关注
世界动态:央行今日进行1960亿元7天期逆回购操作
通江县应急管理局电话地址 世界播资讯
高考查分的心情你还记得吗?一起沉浸式体验|全球关注
资讯推荐:《蝙蝠侠阿卡姆三部曲》实体卡带只有一款游戏!玩家担心NS扛不起
当前播报:土壤分为哪三类 土壤分为哪三类土壤
水彩和水粉的区别是什么
2023年甘肃高考成绩今日公布 高考志愿填报6月27日开始
2023年黑龙江省美容师中级考试题目有哪些?
沉浸交互新升级,PICO联手A-SOUL打造“夏日漫游VR歌会” 今日快看
【环球新视野】分享家常卤鸡肉的简单方法
手机问题:小米11怎么设置24小时-世界最新
焦点热讯:足坛BUFF之子!外公马拉多纳、叔叔梅西、父亲阿圭罗
李轩辕原型人物 李轩辕-焦点快报
热点在线丨孩子记忆力差怎么办_下面小编教你几招
苏州12宗地块今日出让,总起始价约115亿元|天天通讯
中国的激光武器有多厉害?沙特曾用它击落13架无人机,一战成名!
佳能23年Q4推重磅相机EOS R1 天天播资讯
【报资讯】恭喜!妈妈得知孩子高考671分,高兴得给同事发糖庆祝
短讯!国乒无缘5单项决赛!林诗栋等人连续作战,樊振东孙颖莎领衔冲5冠
看守所里的女人们王小虫刘管教_看守所里的女人
“极目锦鲤”名单公布!
环球快消息!再熬77天,四大生肖天赐福气,福禄齐全,内心强大
医用X光机行业市场现状分析及未来发展前景|全球观点
三角函数周期公式推导_三角函数周期公式_天天亮点
高速球机是什么一体的_高速球HTDF718R
焦点热门:新能源行业周报:新能源装机持续高增,新能源车购置税减免延至2027年
当前播报:普里戈任将前往白俄罗斯,俄国防部或收编部分士兵 俄分析师:事件如何发展还有待观察
中药材猛涨登上热搜,业内人士:40年未遇行情
韩媒:一些韩国航空公司暂停部分韩中航班|环球视讯
酷睿Ultra 128MB四级缓存首次现身!核显媲美GTX 1650?_全球播报
全球聚焦:最新汇总!江苏各高校预估分数线出炉→
世界微头条丨天津:7所院校将搬迁至滨海新区
贾跃亭的「前搭档」,拿下了400亿投资 世界今日讯
当前视点!新华社送你一本22城文化指南
国家电影局:2023端午档票房9.09亿元 影史第二-焦点滚动
陆金所理财可靠吗最新_陆金所理财可靠 环球微资讯
17K小说网创始人刘英去世 享年42岁
天天快资讯丨群发精灵_关于群发精灵介绍
当前快讯:在病原菌中鉴定出锌调节剂和抵抗组
明确164项重点工作,商务部印发《自贸试验区重点工作清单(2023—2025年)》 全球微速讯
全球今亮点!264亿元收购案表决在即 兖矿能源详解交易热点
当前时讯:阿根廷人民币使用创纪录
邮储银行白银市分行举办“浓情端午 粽享邮储”活动
环球播报:金昌税务:纳税人致电“市长热线”点赞办税服务大厅
鮰鱼鳍和巴沙鱼鳍区别? 当前热门
端午节北京餐饮迎销售高峰 有餐企预计暑期客流较去年或翻倍增长
工信部:1-5月份我国软件业务收入43238亿元,同比增长13.3% 环球观热点
高培勇:宏观政策要坚持“挤牙膏式”扩张,稳预期得靠改革-天天日报
全球焦点!微信回了个“ OK ”表情手势,他成了被告……
中国电车欧洲热销?“宝藏神车”MG4 EV超过特斯拉、MINI!
最超值的“掀背式动感家轿”?江淮A5 PLUS上市,6.58万元起售-播报
两宗封顶摇号!苏州三批次供地揽金118亿元 全球观热点
丰台区石榴庄街道:“三个坚持”助推两新党建提质增效|观速讯
沈阳:全日制中专以上毕业生购房可享受全额契税补贴 当前观察
视焦点讯!虞城县高中开展法治宣传
被性侵,被家暴,被封杀,37岁童瑶更多“丑闻”曝光:张国立坐不住了!|快讯 全球速递
视频特效师能自学吗
世界最资讯丨这三大星座的女人,最容易嫁入豪门,尤其是第一名,天生少奶奶命!
天天微动态丨基于千兆光网和MEC边缘计算 ,实现“云-网-端”融合协同的智慧工厂创新组网设计
武装分子突袭军车队,酿1死5伤-环球快播报
驻村帮扶有实招 三合界村实现新跨越
高端折叠手机市场再添新成员:三星Galaxy Z Flip5将发布
系列调研:一家基层足球青训俱乐部的困惑与坚守|环球时讯
教你轻松读懂电子电路图|世界动态
今日讯!中国石油天然气集团有限公司原党组副书记、副总经理徐文荣接受审查调查
剧情反转后,俄罗斯现在怎么样?|当前视讯
捷豹路虎召回部分汽车:机油可能泄露,增加起火风险_聚看点
关注:崇礼2023“冬奥骑迹”全民自行车挑战赛开赛
环球最新:1.06亿人次,超2019年同期!端午出游很“热”