利用世界杯,读懂 Python 装饰器 (2)

在这个例子中我们定义了一个 status 函数,status 接收一个函数名然后直接返回该函数名。这样我们实现了不修改原函数 name,并且添加了一个新功能的需求。但是这里有个缺陷就是函数的调用方式改变了。即不是原本的 name,而是 temp。

要解决这个问题很简单,相信 a = a*3 这样的表达式大家都见过,那么上述代码中的 temp = status(name) 同样可以修改为 name = status(name),这样我们就完美的解决了问题:既添加新功能又没有修改原函数和其调用方式。修改后的代码如下:

def status(func):

print('慌的一逼!') return funcdef name():

print('我是梅西!')

name = status(name)

name()

复制代码

但这样的代码却有个不便之处,即每次使用这样的装饰器,我们都要写类似 name = status(name) 的代码。程序员都是懒的,所以才有那么多高级的语法。在 python 中为了简化这种情况,提供了一个语法糖 @,在每个被装饰的函数上方使用这个语法糖就可以省掉这一句代码 name = status(name),最后的代码如下:

def status(func):

print('慌的一逼!') return func@statusdef name():

print('我是梅西!')

name()

复制代码

这样我们就弄清楚了装饰器的工作原理:

1 写一个高阶函数,即参数是函数,返回的也是函数。

2 在利用语法糖@,简化赋值操作。

但是对比开头的例子,还是有些不一样。在开始的例子中,我们还实现了一个 rooftop_status 函数,来判断下当前的天台状是否人满。但是我们现在是直接返回了函数名,这样函数调用后我们就没办法做任何事情。梅西和德国慌了,我们也慌了,各个都要天台见,但在这之前我们也要考虑下天台的情况。

利用世界杯,读懂 Python 装饰器

为了能判断天台的情况,所以此时我们需要在嵌套一层函数,将实现额外功能的部分写在内层函数中,然后将这个内层函数返回即可。这也是为什么装饰器都是嵌套函数的原因。

另外,开篇的例子并没有返回值,也没有参数,要对既有参数又有返回值的函数进行装饰的话,还需要进一步完善。 能够处理返回值的装饰器:

def guess_win(func):

def rooftop_status():

result = func()

print('天台已满,请排队!') return result return rooftop_status@guess_windef german_team():

print('德国必胜!') return '赢了会所嫩模!输了下海干活!'x = german_team()

print(x)

复制代码

输出结果:

德国必胜!

天台已满,请排队!

赢了会所嫩模!输了下海干活!

复制代码

能够处理参数的装饰器:

def guess_win(func):

def rooftop_status(*args, **kwargs):

result = func(*args, **kwargs)

print('天台已满,请排队!') return result return rooftop_status@guess_windef german_team(arg):

print('{}必胜!'.format(arg)) return '赢了会所嫩模!输了下海干活!'x = german_team('德国')

y = german_team('西班牙')

print(x)

复制代码

输出结果:

德国必胜!

天台已满,请排队!

西班牙必胜!

天台已满,请排队!

赢了会所嫩模!输了下海干活!

复制代码

总结

装饰器的本质是函数,其参数是另一个函数(被装饰的函数)。装饰器通常会额外处理被装饰的函数,然后把它返回,或者将其替换成另一个函数或可调用对象。行为良好的装饰器可以重用,以减少代码量。

对于这届的世界杯,我总结了下。

利用世界杯,读懂 Python 装饰器

我有一个微信公众号,经常会分享一些python技术相关的干货;如果你喜欢我的分享,可以用微信搜索“python语言学习”关注

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zydsjx.html