python装饰器就是用于扩展原函数功能的一种函数,这个函数特殊的地方就是它的返回值也是一个函数,使用Python装饰器的一个好处就是:在不需要修改原函数代码的情况下,给函数增加新的功能。
先来看个例子:
def say(): print('Nice day') say() # 这个函数的输出为: Nice day
现在,我想在输出Nice day
的前面再打印一行****************
,类似下面的效果:
****************
Nice day
一般情况下,我可以修改上面的代码:
def say(): print('****************') print('Nice day') say()
可是,如果我忽然发现自己看错了需求,这时候又要把代码修改到原来的样子,庆幸的是我只是在原来函数的基础上增加了一行代码,想要回到原来的状态并不难,可如果我是修改了复杂的逻辑,代码有一百行呢,难道我还要一步步撤销吗?显然做不到,不过没关系,肯定还有别的办法:
def say(): print('Nice day') def outer(): # 重新定义一个新函数 print('****************') # 处理新的逻辑 say() # 再调用原来的函数 outer() # 现在的输出为: ''' **************** Nice day '''
怎么样,看上去已经满足要求了吧,不过仔细一看,就能发现新的问题,如果不仅仅是say()
函数需要打印****************
,新来的talk()
函数也需要呢,这时候我又要再写一个outer()
函数吗?这会累坏丹丹的,所以得再想个办法:
def say(): print('Nice day') def talk(): print('I am talk') def outer(func): # 接收一个函数 print('****************') # 处理新的逻辑 func() # 调用传递过来的函数 outer(talk) # 把talk函数作为参数传递过去 # 输出结果如下: ''' **************** I am talk '''
这时,不管有几个函数需要打印****************
,我直接把函数名传给outer()
就可以啦,是不是方便很多^-^ 但是勤劳的丹丹会止步于此吗?肯定不会,于是又把代码做了如下修改:
def say(): print('Nice day') def outer(func): def inner(): print('****************') func() # 相当于 say() return inner s = outer(say) # 相当于 s = inner s() # 相当于 inner()
猜猜这次的是输出是什么~当然还是和上面一样啦!其实这里只是把处理逻辑的部分封装在了一个函数里面,调用outer(say)
的时候,把say
传给outer
,获得返回值inner
给s
,此时的s
就相当于inner
,s()
也就相当于inner()
,所以会输出:
**************
Nice day
这就是一个最简单的装饰器啦,是不是很简单~ 但是我们每次在使用的时候还需要先赋值给一个变量(这里的s),然后再经由s调用,未免违反了丹丹“多一行代码都是累赘”的原则,所以我们再修改一下代码:
def outer(func): def inner(): print('****************') func() return inner @outer # 用outer装饰say def say(): print('Nice day') say() # 调用say函数
我把outer
和say
调换了一下位置,先定义了outer
函数,@outer
表示用outer
装饰say
,这样直接用say()
就能实现我想先打印一行****************
的功能了,如果不调换两个函数的位置,是会报NameError: name 'outer' is not defined
的错误的噢(作用域的原因,outer
未定义),这个应该算是复杂一点的装饰器了吧,哈哈
这时候很多细心同学肯定就会问了,你写的都是无参的呀,那如果我的函数有参数怎么办呢,参数还是不固定的又该怎么办呢?万能的python+聪明的丹丹当然可以解决:
# 带参数的装饰器 def outer(func): def inner(name): func(name) return inner @outer def say(name): print('name is %s.' % (name)) say('dandan') # name is dandan.
不过这个参数个数是固定的,万一我又突发奇想,想多传一个hobby
或者age
怎么办呢?
# 带不定参数的装饰器 def outer(func): def inner(*args, **kwargs): func(*args, **kwargs) return inner @outer def say(name, age): print('name is %s, age is %d.' % (name, age)) @outer def talk(name, age, hobby): print('name is %s, age is %d, hobby is %s.' % (name, age, hobby)) say('dandan', 18) talk('dandan', 18, 'Coding') ''' name is dandan, age is 18. name is dandan, age is 18, hobby is Coding. '''
如果我要新增的功能有很多,一个装饰器搞不定,怎么办呢?我可以同时使用多个装饰器吗?当然可以:
# 多个装饰器 def outer(func): def inner(*args, **kwargs): print('****************') func(*args, **kwargs) return inner def outer2(func): def inner2(*args, **kwargs): print('这里有1w+新功能') func(*args, **kwargs) return inner2 @outer @outer2 def say(name, age): print('name is %s, age is %d.' % (name, age)) @outer @outer2 def talk(name, age, hobby): print('name is %s, age is %d, hobby is %s.' % (name, age, hobby)) say('dandan', 18) talk('dandan', 18, 'Coding') ''' **************** 这里有1w+新功能 name is dandan, age is 18. **************** 这里有1w+新功能 name is dandan, age is 18, hobby is Coding. '''
要注意的是,多个装饰器的执行顺序是从第一个装饰器开始,执行到最后一个装饰器,再执行函数本身。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]