如何理解使用Python的装饰器
首先Python 的装饰器值是一种语法糖,用于动态修改函数或类的行为
大白话就是Python的装饰器只是Python语法指令的简单写法,他是用来修饰类和函数实现一些辅助功能,不使用装饰器也可以,可能实现起来比较麻烦(优雅是Python追求的特点之一)!
Python装饰器的基本原理:一个函数可以接受另一个函数作为参数,然后返回一个新的函数一个引例def log(func): def wrapper(*args, **kw): print("call %s():" % func.__name__) return func(*args, **kw) return wrapper @log def my_func(*args, **kw): print("hello world")
在这个例子中定义了一个装饰器 log,它接受一个函数作为参数,然后返回一个新的函数 wrapper。wrapper 函数中输出了一段日志,并调用原来的函数 func。
我们用 @log 语法将装饰器应用到了 my_func 函数上,相当于执行了如下语句:my_func = log(my_func)
这样,再用 my_func() 函数时,log函数把my_func() 函数的参数打包给了wrapper()函数,wrapper()函数在执行之前会对my_func() 函数进行一些装饰!然后再执行my_func() 函数。
那么问题来了?为什么会执行wrapper()函数呢,我们仅仅是定义了它,并没有调用,看到log函数结束时的返回语句:return wrapper 就是对wrapper的调用,那这样顺序就里清楚了
当然你也可以选择不用装饰器,实现相同的效果,那样程序就得改成这样:def log(func,*args,**kw): print("call %s():" % func.__name__) return func(*args, **kw) def my_func(*args, **kw): print("hello world") log(my_func)
这样你每次运行my_func函数的时候外面就得套个log函数,而且当my_func函数有参数时,你还得把参数传递给log,就显得调用起来十分麻烦!装饰器的精髓就是装饰器函数把它需要修饰函数的参数一同打包传递给了内部定义的函数,并且执行内部定义的函数装饰器的其它应用计时装饰器:记录函数执行时间。缓存装饰器:将函数的返回值缓存起来,避免重复计算。权限验证装饰器:检查用户是否有访问某个页面的权限。日志记录装饰器:记录函数的执行结果或异常信息
一个计时装饰器的例子import time def timer(func): def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) end_time = time.time() print(f"函数 {func.__name__} 执行时间:{end_time - start_time}") return result return wrapper @timer def my_func(n): time.sleep(n) my_func(2) # 输出:函数 my_func 执行时间:2.0025088787078857
这个不必多说,和上面log()装饰是一个道理,你可以尝试不用装饰器实现上面的功能!
在这个例子中,定义了一个计时装饰器 timer,它会在函数执行前记录开始时间,执行后记录结束时间,并输出函数执行时间。然后,我们用 @timer 将它应用到了 my_func 函数上,这样每次执行 my_func(n) 函数时,都会输出函数执行时间Python中一些特定的装饰器
1、@property:用于将一个方法转化为只读属性。可以让我们在不改变原有代码的情况下,对类的外部接口进行改进class MyClass: def __init__(self, x): self._x = x @property def x(self): return self._x c = MyClass(10) print(c.x) # 输出:10
在这个例子中,定义了一个类 MyClass,其中包含一个私有属性 _x,和一个方法 x,并用 @property 装饰器将方法转化为只读属性。这样,在外部访问 c.x 时,实际上是调用了 c.x() 方法
2、@staticmethod:用于将一个方法转化为静态方法。静态方法可以直接通过类名调用,不需要实例化对象class MyClass: @staticmethod def f(x, y): return x + y print(MyClass.f(10, 20)) # 输出:30
在这个例子中,我们定义了一个类 MyClass,其中包含一个静态方法 f,并用 @staticmethod 装饰器将其转化为静态方法。这样,在外部调用 MyClass.f 时,不需要实例化 MyClass 对象。
3、@classmethod:用于将一个方法转化为类方法。类方法的第一个参数是类对象,可以通过它访问类的属性和方法。class MyClass: x = 10 @classmethod def f(cls): return cls.x print(MyClass.f()) # 输出:10
在这个例子中,我们定义了一个类 MyClass,其中包含一个类属性 x,和一个类方法 f,并用 @classmethod 装饰器将其转化为类方法。这样,在类方法中可以通过第一个参数 cls 访问类属性 x
4、@functools.wraps:用于修饰装饰器。如果我们定义一个装饰器,它会修改被装饰函数的行为,但是在外部调用被装饰函数时,函数的名称和文档字符串会发生改变。为了保留原有的名称和文档字符串,可以使用 @functools.wraps 装饰器。import functools def my_decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): print("Calling decorated function") return func(*args, **kwargs) return wrapper @my_decorator def example(): """Docstring""" print("Called example function") print(example.__name__) # 输出:"example" print(example.__doc__) # 输出:"Docstring"
如果对Python编程感兴趣,可以私聊小编!
#编程##Python#
江华公安局为群众挽回被骗资金14万余元红网时刻新闻10月12日讯(通讯员刘雯娟吴思)近期,江华公安局刑侦大队接连侦破两起诈骗案,为受害群众挽回损失共14万余元。2017年至2018年,嫌疑人周某因急需还贷款,便打着虚构
时刻夜谈丨抗议示威在多国蔓延!欧洲处处都是风景线2022年10月12日晴今日值班刘经纶郑重时刻夜谈第21期谢谢你,马克龙!我50分钟就能加到油!10月10日,法国巴黎一名出租车司机在排队加油时感谢了一番法国总统马克龙,他还埋怨道
把绿色能源送到千家万户武钢在接受媒体采访。新华社记者王菲摄一年一场风,从春刮到冬。达坂城地处新疆乌鲁木齐东南方位的天山豁口,风力强劲。上世纪80年代,达坂城的戈壁滩上建起风电场。1987年,武钢主动放弃
额度更高时限更长,天安数码城获股东贷款额再增1。8亿10月11日下午,天安与联合集团发布公告,披露向天安数码城提供的股东贷款本金增加一事。公告显示,于发布当日(10月11日),天安(联合集团之间接非全资附属公司)与天安数码城(天安直
湘西十八洞村精准绣花生机勃发湖南湘西十八洞村地处武陵山脉腹地,这里山高林密,人均耕作面积少,村民生活曾长期徘徊在贫困线以下。由长城新媒体集团主创,学习强国河北学习平台联合学习强国湖南学习平台共同推出的原点的故
保险营销员业绩进一步分化人数下降同时稳定性有大幅提升21世纪经济报道记者胡天姣深圳报道保险销售人员在群体规模下降的同时,该群体本身也在发生一些结构变化。10月12日,北京大学汇丰商学院风险管理与保险研究中心和保险行销集团保险资讯研究
宁远县委退役军人事务工作领导小组召开2022年第一次全体会议红网时刻新闻10月12日讯(通讯员何勇辉廖芷谊)10月11日上午,宁远县委退役军人事务工作领导小组召开2022年第一次全体会议,县委书记胡勇刚出席并讲话,毛政廖劲松齐纲要邓建华等县
芙蓉国评论丨从我出发,以进击姿态喜迎二十大金宇10月16日,中国共产党第二十次全国代表大会将在北京召开,全国人民正以饱满的政治热情,迎接党的二十大到来。广大党员干部要胸怀大我境界永葆无我情怀保持忘我状态,坚持从我出发奔赴新
跟对象最暧昧上头的瞬间??real羞的要死啊啊啊俗话说得好独乐乐不如众乐乐情侣间的聊天截图我这个万年单身狗可以说是百看不厌又是我为网友们美好爱情流泪的一天铁汁们快来一起跟着我吃下这波狗粮一个敢问一个敢答你好会说哇总会有人懂你的奇
女儿晒父母32年前的情书走红,网友发现了爸爸追妈妈的套路近日,青岛一女子无意翻到32年前爸爸追求妈妈时的书信,今天抽点时间给你草书一封,希望你别生我的气其中还有宋女士爸爸写给其他家人的书信,叔婶,全家好。天气冷了,随信给二叔寄了双鞋信里
广西山清水秀生态美八桂大地绿生金央视网消息(记者王静远彭俊吕媛媛)近日,由中央网信办网络传播局国家林业和草原局宣传中心联合指导,内蒙古自治区党委网信办广东省委网信办广西壮族自治区党委网信办陕西省委网信办甘肃省委网