1 写在前面
python中使用@
放在函数上方便定义一个装饰器
,很多朋友觉得使用装饰器太魔幻,始终不知道怎么灵活使用。
要想做到灵活使用,得首先明白它的本质。今天,我试着用最通俗的语言,几行代码和小例子来解释装饰器的本质
。
2 小例子
这是一个装饰器:
def call_print(f):
def g():
print('you\'re calling %s function'%(f.__name__,))
return g
使用call_print
装饰器:
@call_print
def myfun():
pass
@call_print
def myfun2():
pass
myfun()后返回:
In [27]: myfun()
you're calling myfun function
In [28]: myfun2()
you're calling myfun2 function
3 使用call_print
你看,@call_print
放置在任何一个新定义的函数上面,都会默认输出一行,你正在调用这个函数的名。
这是为什么呢?注意观察新定义的call_print
函数(加上@后便是装饰器):
def call_print(f):
def g():
print('you\'re calling %s function'%(f.__name__,))
return g
它必须接受一个函数f
,然后返回另外一个函数g
.
4 装饰器本质
本质上,它与下面的调用方式效果是等效的:
def myfun():
pass
def myfun2():
pass
def call_print(f):
def g():
print('you\'re calling %s function'%(f.__name__,))
return g
下面是最重要的代码:
myfun = call_print(myfun)
myfun2 = call_print(myfun2)
大家看明白吗?也就是call_print(myfun)后不是返回一个函数吗,然后再赋值给myfun.
再次调用myfun, myfun2时,效果是这样的:
In [32]: myfun()
you're calling myfun function
In [33]: myfun2()
you're calling myfun2 function
你看,这与装饰器的实现效果是一模一样的。装饰器的写法可能更加直观些,所以不用显示的这样赋值:myfun = call_print(myfun)
,myfun2 = call_print(myfun2)
,但是装饰器的这种封装,猛一看,有些不好理解。
怎么样,相信你会有一些收获,恭喜你!这是我的原创,如果可以,帮我分享一下吧。
近期小例子:pyecharts绘制词云图;使用pillow处理图片,很简单!;slice对象的应用举例;一行代码优化异常输出;函数的五类参数使用例子;绘制时间线轮播图;python参数类型使用总结;绘制水球图;lambda参数之坑;Python绘制仪表盘;参数的默认值陷阱!;chain串联多个迭代对象;机器学习中会涉及到的随机选择样本;使用namedtuple的小例子; pkuseg 做分词,超级nice~; 写一个装饰器:统计异常发生次数和时间;对象可被调用的实现方法;求任意维度两点间距离; 两种合并字典的方法对比; 计算和聚合同时进行; groupby 分组; plotly画柱状图+折线图;
有收获,点个在看;想要了解更多小例子,点击阅读原文