专栏文章 他山之石可以攻玉——继续深入理解 python 装饰器

我去催饭 · 2021年11月26日 · 最后由 我去热饭 回复于 2021年11月26日 · 2226 次阅读

看看无敌哥是如何讲装饰器的

今天的参考文章来自【测试开发坑货】(作者米洛,人称 Woody 哥/无敌卷魔/测开届的肝帝等等),继续学习 python 的装饰器语法基础。目标就是彻底地理解它,学会它。一次不行就一百次,读过《笨办法学 python》的同学都知道,看十遍也不如照着敲一遍来的印象深,更何况我这个水平的菜鸟。所以,千万别犯懒,一字一句,照着敲起来,这次我们调皮一点:

def simple(func):
    def wrapper():
        print("无敌哥开始卷了")
        func()
        print("无敌哥卷完了")

    return wrapper

@simple
def func():
    print("无敌哥正在卷ing")

def func1():
    print("没有@wrapper无敌哥也在卷")

if __name__ == "__main__":
    func()
    print("----分割线----")
    simple(func1)()
    print("----分割线----")
    f = simple(func1)
    f()

这个例子,无敌哥进行了非常详细的讲解。将@wrapper这个比较抽象的语法,拆解为了 simple(func1)() 这种形式,如果还不理解,就干脆再拆一步,变成 f=simple(func1) 和 f(),这下连我都看懂了,想必各位也一定明白了:

simple(func1) 返回了 wrapper 这个对象,这个对象本身又是一个函数,赋给 f 这个变量,f() 则执行了返回的 f 方法,所以合并到一起就是 simple(func)(),这样拆出来就更好理解了。所以装饰器的本质就是一个 function 而已,只不过 @ 的写法会便捷很多。不要再认为装饰器是什么很高深的写法了,其实理解下来就是个函数套娃的操作。

执行结果如下:

无敌哥开始卷了
无敌哥正在卷ing
无敌哥卷完了
----分割线----
无敌哥开始卷了
没有@wrapper无敌哥也在卷
无敌哥卷完了
----分割线----
无敌哥开始卷了
没有@wrapper无敌哥也在卷
无敌哥卷完了

接下来无敌哥进一步讲解了装饰器的用法:带参数的装饰器。有了上面的基础概念,这次理解容易多了,还是要亲手敲出来才比较有感觉:

def simple(func):
    def wrapper(*args,**kwargs):
        print("无敌哥又开始卷了")
        func(*args,**kwargs)
        print("无敌哥又卷完了")

    return wrapper

@simple
def func(a,b,key="无敌哥流批"):
    print(a,b,key)
    print("无敌哥正在卷ing")

if __name__ == "__main__":
    func(['饭佬',666],{'汤总':'9分女管理'})

运行一下可以看到,和上面相比,多出了一些参数功能,args,*kwargs 有啥区别这里就不赘述了,一个列表一个字典,至于为啥它俩一前一后固定这样,有面试官会问,别问,问就是语法就这么规定的,你不按套路出牌他就给你报错。

无敌哥又开始卷了
['饭佬', 666] {'汤总': '9分女管理'} 无敌哥流批
无敌哥正在卷ing
无敌哥又卷完了

用这个写法还有一个好处就是灵活,参数有多个的话就处理成列表或者字典形式,都能接收,避免了由于参数变化导致的报错.

学废了吗?做做无敌哥留的小作业?

我想要一个循环执行 N 次方法的装饰器,命名为 loop,如果@loop形式,则不进行循环,如果是@loop(5),则要循环方法 5 次,你可以试试吗?

@loop
def func1():
    "无敌哥卷起来了"
@loop(5)
def func2():
    "无敌哥卷了5次"

试试就试试:

完,学废了,欲知后事如何,且看下回分解,强悍的无敌哥,一个装饰品能写 3 篇大论,真乃神人也。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 1 条回复 时间 点赞
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册