实际上就是闭包的"快捷写法"
学习的过程中主要是要容易搞混参数的问题
1.装饰器有参数
2.被修饰的函数也有参数
3.返回的函数有参数
主要是要讨论这三个问题,首先,看下默认情况:
调用被修饰的函数前会找把这个函数作为参数传递给装饰器,然后装饰器返回一个闭包,然后再调用
#这货是个装饰器,我们主要是,让它输出"小明 说了啥"
def say(person):
def inner(what):
print(person()+"说了"+what)
return inner
@say
def xm():
return "小明"
xm("你好")
首先有点好奇的是:
函数xm不是没有参数的么,怎么调用的时候又带了个,这样的确让人摸不着头脑
我们尝试下一句句理解
1.xm是一个不带参数的函数
2.当say修饰它的时候,会先调用say,默认把xm作为参数传递给say(先不管xm参数的去向,前后再撸一撸。然而这里的xm并没有参数。哇咔咔(︶︿︶)=凸)
3.我们在say函数中定义了一个函数inner,say执行结束后把inner返回,也就是调用完say后返回的对象是函数对象
4.我们看看inner,它有一个参数what,实际上最后返回的函数形如func(arg)这样的格式(大概猜到后面跟的参数是怎么来的吧),xm()它压根不是调用xm!!!惊喜不惊喜,意外不意外(头点点笑嘻嘻,一口老血mmp),为什这么说,因为,xm作为参数传递给say,点不调用xm,完全看say怎么写,不信是把,我们写个例子
#请注意,此处未调用func
def say(func):
def inner(what):
print(what)
return inner
def xm():
return "小明"
xm("喵喵喵?")
mmp,压根没调用xm,最后的写法果然想迷惑老夫?d(ŐдŐ๑)实际上等价于写成的
def say(func):
def inner(what):
print(what)
return inner
def xm():
return "小明"
say(xm)("喵喵喵")
好了,写到这里的时候,自己基本吧简单的那种情况捋顺了,现在问题来了,即使写一个很简单的装时期,也涉及到三个参数,如果每一个参数都有函数,那么,就更加头大了,笑嘻嘻(MMP)
多个参数的情况
条件:
1.装饰器有参数
2.被修饰的函数有参数
3.闭包也有参数
形如这样的
@say("小明")
def who(name):
return name
笑嘻嘻(mmp),我的装饰器要怎么写,好,尝试下怎么写的
#coding:utf-8
def say(name):
def inner(person):
def whoSay(what):
print(person(name)+"说了"+what)
return whoSay
return inner
@say("小明")
def who(name):
return name
who("你好")
感觉和之前的不太一样对吧,因为之前的情况是被修饰的函数直接作为参数传递给修饰器,然后这种装饰器是带参数的,他的参数表其实就是在上面的小明
,但是,who怎么作为参数传进去的呢?别着急,say调用完毕后,返回一个函数inner,这个才等价于之前那种情况,它会把who作为参数传进去,然后,它再返回whoSay,然后就是之前那种情况了,我们来看看,如果不用装饰器他是可以这样写的
#coding:utf-8
def say(name):
def inner(person):
def whoSay(what):
print(person(name)+"说了"+what)
return whoSay
return inner
def who(name):
return name
say("小明")(who)("你好")
更加猛烈一些吧
如果是多层装饰器又是什么情况
形如这样的
@sayAgain
@say
def who():
return "小明"
笑嘻嘻(mmp),怎么写嘛
尝试下根据之前的规律,他一层的时候who的时候等价于say(who),此时的返回值是一个函数,如果嵌套,我猜测是sayAgain(say(who)),那么,最终sayAgain接受的参数是say返回的函数,然后,sayAgain自己再返回一个函数,如果是who("你好"),就成了,sayAgain(say(who))("你好")
然后我尝试下写
#输出小明说了你好,再见
#这里sayAgain接受的person实际是say的inner
def sayAgain(person):
def inner():
print(person()+",再见")
return inner
#这里接受的person是who
def say(person):
def inner():
return person()+"说了你好"
return inner
@sayAgain
@say
def who():
return "小明"
who()
#所以这里的who其实等价于
#sayAgain(say(who))()
所总结出来的规律就是:多层嵌套的时候,上面
的装饰器接受的参数
,都是下面
装饰器返回
的函数(也就是被装饰过的函数),这样可以多层进行嵌套,感觉吊(M)吊(M)哒(P)
什么!还有更变态的?
如果每个装饰器都有参数,然后多层嵌套会是怎么样一种情况?我....擦,硬着来搞一下
根据之前带参数的装饰器的规律,装饰器的参数表已经知道了,然后它返回一个函数接受被修饰的函数作为参数,然后,再返回修饰后的函数,如果,多层也得遵循这个规律,我们看看这样的怎么写
@say("你好")
@person("小明")
def who(name):
return name
宝宝硬要写
目标是输出:谁说了啥
#coding:utf-8
#这个修饰器主要是吧要说的内容加进去
def say(what):
def inner(func):
def personSay():
print(func()+what)
return personSay
return inner
#这个修饰器主要是确定是谁在说
def person(name):
def inner(func):
def innerWhoSay():
return func(name)+"说了"
return innerWhoSay
return inner
@say("你好")
@person("小明")
def who(name):
return name
#被修饰的函数只是单纯的返回名字
#喵喵喵?这里居然who不带参数?那被修饰的函数参数哪里体现出来?其实在修饰器!
who()
那么其实等价于
say("你好")(person("小明")(who))()
大吉大利!
好比如说你有个小gun gun(98k),然后,你要给他加配件(修饰)让他功能更强大,然后,你先装上了枪托,然后再装个8倍镜,然后biubiubiu,下面用装饰器来尝试输出这样的结果
$ python3 98k.py
98k已到手
已安装枪托配件
已安装8倍镜
目标命中!
$
代码如下
#coding:utf-8
#98k打一枪
#枪托
def stock(gun):
def inner():
gun()
print("已安装枪托配件")
return inner
#瞄准镜
def Sights(ratio):
def inner(gun):
def getSights():
gun()
print("已安装"+str(ratio)+"倍镜")
return getSights
return inner
#开枪
def shot(gun):
def inner():
gun()
print("目标命中!")
return inner
@shot
@Sights(8)
@stock
def gun():
print("98k已到手")
#选用了4倍镜biubiubiu
gun()
网友评论