python装饰器测试与理解

第一,装饰器基础语句

# 这是一个基本的装饰器测试文件
def deco(func):
    def mod():
        func()
        print("I'm mod")
        #mod函数在接收的func函数基础上,后置增加了print功能
    return mod
    # 将func拓展为mod后,返回新函数mod。
    # 这,就是本deco函数的使命。

# 所以假设main函数如下:
def main():
    print("I'm main")
    pass
# 则可以有:
a = deco(main) # 满足deco的参数要求,使其完成使命
a() 
# 输出结果为:
#I'm main
#I'm mod

# 鉴于deco(main)返回的本质是一个函数,甚至可以有:
deco(main)()
# 输出结果同样为:
#I'm main
#I'm mod

第二,它是不是装饰器?装饰器的运行逻辑是什么?

# 装饰器的运行逻辑
def deco(func):
    print("I'm deco")
    def mod():
        print("I'm mod")
        pass
    return func
    #这一次将func原样返回,mod也未对func作修改。

def main():
    print("I'm main")

a = deco(main)
a()
# 运行结果为:
# I'm deco
# I'm main
# I'm main

# 为什么deco在前?
# 因为a = deco(main)本身也产生输出,而a()产生的输出只有一句
# 不信试试这个:

a()
deco(main)
# 输出结果为:
# I'm main      由a()生成
# I'm deco      由deco函数生成

#总结:
# 1.装饰器一般分内外2层,才能达到‘装饰’的目的。
# 2.内层必须对其对func函数有所操作,否则无法起到
#   ‘装饰器的作用’。
# 3.a()的本质,是执行且仅执行一个函数,
#   就是deco返回的那个函数。

第三,@语法糖

标准的@语法糖

# @语法糖
def deco(func):
    def mod():
        func()
        print("I'm mod")

    return mod

@deco
def main():
    print("I'm main")

main()
# 最终输出为:
# I'm main
# I'm mod

# @deco这一行语句,实现了如下的基本功能:
#  1.实现了deco(main)这条语句
#  2.实现了将deco(main)赋值给一个也叫main的变量。
#    这相当于a=a+5。 a+5的值,完成了对原来a的覆盖
# 综上,@deco这一句,相当于,且仅相当于main = deco(main)

# 这样写的好处:
#  1.没有改变main的调用方法。(尽管内部新main替换了老main)
#  2.没有改变原main函数的内部性质。(依然可以打印出I'm main)
# 以上也是一个良好装饰器的必备特质。例如本例中def的deco
#  ,就具备这样的特质

@语法糖的运行逻辑

# @语法糖的运行逻辑
def mod2(func):
    func()
    print("I'm mod2")
    return mod2

@mod2
def main2():
    print("I'm main2")

# main2()
# 以上是正常程序,并作了2处改动:
# 1.这一次我没有调用main2(),将它注释掉了。
# 2.原本deco函数内还定义了一层mod,这次将deco外壳删掉
#   只留下了mod

#最终输出:
# I'm main2
# I'm mod2

# 那么@mod2,相当于执行了一次mod2内的所有语句。注意,
# 这是在没有进行main2()语句调用时,就执行过一次的。
# 参考‘它是不是装饰器?’的内容,相当于执行了mod2(main2)这
# 一语句。
# 下面,你可以试试将mian2()的注释去掉,看看会发生什么。

带返回值的@语法糖

# 带参数的语法糖
def deco(func):
    def mod():
        temp = func()
        print("I'm mod")
        return temp

    return mod

@deco
def main():
    print("I'm main")
    return "I'm main return"

a = main()
print('----分割线')
print(a)
# 最终输出:
# I'm main
# I'm mod
# ----分割线
# I'm main return

# 装饰器是围绕原函数服务的。本例中,因为main多了return语句,所以
# 装饰器应当为保留return 内的信息,而作出改变。在本例中,多了
# return temp及其配合语句temp = func(),来实现参数传递。传递线路为:
# 老main函数的'I'm main return' ,通过func(),传递给temp, 
# 由temp返回给mod函数,mod函数加上了其它拓展后,新函数mod又
# 写覆盖给新main函数,使return在新main函数中实现。

带参数的@语法糖

# 带参数的语法糖
def deco(func):
    def mod(arg1, arg2):
        temp = func(arg1, arg2)
        print("I'm mod")
        return temp

    return mod

@deco
def main(a, b):
    print(a + b)
    return "I'm main return"

a = main(1, 1)
print(a)
# 最终输出:
# 2
# I'm mod
# I'm main return   #这一句由print(a)输出

# 比较简单,还是围绕main作装饰器修改。当def mian时,
# 出现a,b两个参数时,deco中的mod函数,也应当对应出现
# 两个参数,这里取名为arg1, arg2。最终main(1,1)
# 调用时,既完成了1+1的操作,也完成了输出"I'm mod"的操作。

带可变参数的@语法糖

# 带参数的语法糖
def deco(func):
    def mod(*x1, **x2):
        temp = func(*x1, **x2)
        print("I'm mod")
        return temp

    return mod

@deco
def main(a, b, c, d):
    print(a + b + c + d)
    return "I'm main return"

a = main(1, 1, 1, 1)
print(a)
# 最终输出:
# 4
# I'm mod
# ----分割线
# I'm main return   #这一句由print(a)输出

# 依旧,当main变为4个参数时,我们对装饰器作被动修改。当def mian时,
# 但程序员想偷懒了,索性在def mod时,修改参数为*x1和**x2,大功告成!

参考

cnblog:Python装饰器
X乎答案:Python 装饰器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值