您当前的位置:首页 > IT编程 > python
| C语言 | Java | VB | VC | python | Android | TensorFlow | C++ | oracle | 学术与代码 | cnn卷积神经网络 | gnn | 图像修复 | Keras | 数据集 | Neo4j | 自然语言处理 | 深度学习 | 医学CAD | 医学影像 | 超参数 | pointnet | pytorch | 异常检测 | Transformers | 情感分类 | 知识图谱 |

自学教程:python装饰器代码深入讲解

51自学网 2021-10-30 22:53:51
  python
这篇教程python装饰器代码深入讲解写得很实用,希望能帮到您。

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 inners = outer(say) # 相当于 s = inners() # 相当于 inner()

猜猜这次的是输出是什么~当然还是和上面一样啦!其实这里只是把处理逻辑的部分封装在了一个函数里面,调用outer(say)的时候,把say传给outer,获得返回值inners,此时的s就相当于inners()也就相当于inner()所以会输出:

**************

Nice day

这就是一个最简单的装饰器啦,是不是很简单~ 但是我们每次在使用的时候还需要先赋值给一个变量(这里的s),然后再经由s调用,未免违反了丹丹“多一行代码都是累赘”的原则,所以我们再修改一下代码:

def outer(func): def inner(): print('****************') func() return inner@outer # 用outer装饰saydef say(): print('Nice day')say() # 调用say函数

我把outersay调换了一下位置,先定义了outer函数,@outer表示用outer装饰say,这样直接用say()就能实现我想先打印一行****************的功能了,如果不调换两个函数的位置,是会报NameError: name 'outer' is not defined的错误的噢(作用域的原因,outer未定义),这个应该算是复杂一点的装饰器了吧,哈哈
这时候很多细心同学肯定就会问了,你写的都是无参的呀,那如果我的函数有参数怎么办呢,参数还是不固定的又该怎么办呢?万能的python+聪明的丹丹当然可以解决:

# 带参数的装饰器def outer(func): def inner(name): func(name) return inner@outerdef 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@outerdef say(name, age): print('name is %s, age is %d.' % (name, age))@outerdef 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 innerdef outer2(func): def inner2(*args, **kwargs): print('这里有1w+新功能') func(*args, **kwargs) return inner2@outer@outer2def say(name, age): print('name is %s, age is %d.' % (name, age))@outer@outer2def 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.'''

要注意的是,多个装饰器的执行顺序是从第一个装饰器开始,执行到最后一个装饰器,再执行函数本身。

到此这篇关于python装饰器代码深入讲解的文章就介绍到这了,更多相关python装饰器内容请搜索51zixue.net以前的文章或继续浏览下面的相关文章希望大家以后多多支持51zixue.net!


Pytorch如何切换 cpu和gpu的使用详解
python 如何在测试中使用 Mock
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。