装饰器之变体装饰

来源:互联网 发布:拼团软件排行 编辑:程序博客网 时间:2024/04/27 15:05

装饰器就是用来装饰东西的,一般情况下用来装饰方法,在不修改原方法的情况下让原方法拥有更多的功能

简单实现

def test():    print('test')test()  #testdef godme(fun):    def __godme():        print('before')        result = fun()        print('after')    return __godme@godmedef test():    print('test')test()'''testbeforetestafter'''
原来的方法没有改变,但是功能更多了,没有改动方法的内部,却拥有了更多的周边操作

这也是装饰器的本质含义:保持方法的独立性,只增添周边装饰的操作,执行前前或执行后

也是装饰器的根本局限:永远只能修饰,不能更改原方法内部操作

但是装饰之外,装饰器还有一个特殊的功能,就是执行修饰的方法

def godme(fun):    fun()    @godmedef test():    print('test')test    #test
这样直接打名称就能够执行了,不用加括号调用了

那么,装饰器的本质是什么呢

def godme(fun):    test()def test():    print('test')godme(test)     #test
好像明白一点了,继续看
def godme(fun):    def __godme():        test()    return __godmedef test():    print('test')new_test = godme(test)     new_test()          #test
明白了吧,装饰器就是把方法当做入参和返回值的方法

添加操作,然后执行方法,继续添加操作,这就是为什么它能够执行方法,修饰方法却不能修改方法内部

同时,方法已经在装饰器方法内部调用过了,本身执行也就不用括号了,要添加括号的话装饰器返回的就必须是一个方法

所以能够总结出两点:

1.装饰器就是把方法当做入参和返回值的类方法(返回值可以为None,装饰方法不能括号调用执行)
2.@修饰符号就是表示把修饰的方法当做入参传入装饰器,并把装饰器返回值赋给被修饰的方法名称

说白了,装饰器就是

test = godme(test)
不用符号也可以手动传参执行,不过就是比较low罢了

既然明白了装饰器也是方法,符号修饰只是自动入参这两点,于是我们还可以这样做

def out(fun):    print('out')    return fun@outdef godme(fun):    print('godme')    return fun@godmedef test():    print('test')test()'''outgodmetest
装饰器装饰装饰器?还可以这样玩
def out(fun):    print('out')    return fundef godme(fun):    print('godme')    return fun@out@godmedef test():    print('test')test()'''godmeouttest'''
好玩,不过有三点点东西值得在意一下

1.装饰技巧:如果装饰操作涉及在方法执行之后,我们就必须在装饰器内部定义一个方法,然后在定义的方法里面执行这个方法,再返回定义的方法(舌头打结了)

def test():    print('test')def godme(fun):    def __godme():        print('before')        fun()        print('after')    return __godme
不过如果不涉及执行之后的操作之后的话,不就是定义装饰操作之后直接返回方法对象了么,真特么的简便

2.参数限制:入参是函数而已,我们可以随便定义入参个数,然后内部调用这些函数

                     不过想用符号标记的话,一次好像只能标记一个方法啊,考虑到默认参数的可能,我特地试了一下

def show():    print('show')def godme(fun,two=show):    def __godme():        show()        print('before')        fun()        print('after')    return __godme@godmedef test():    print('test')test()'''showbeforetestafter'''
我擦,真的可以,所以,装饰器方法只能有一个无默认值参数,却是可以增加多个默认值参数,在内部进行更多元的操作

只有一个参数的话,默不默认都会被替换成入参值

3.装饰顺序:层级装饰的话没有意见,但是一个方法添加多个装饰器好像顺序有点疑问的样子,测试一下

def show(fun):    print('show')    return fundef what(fun):    print('what')    return fundef godme(fun):    print('godme')    return fun@what@show@godmedef test():    print('test')test()'''godmeshowwhattest'''
所以,符号修饰的话,最外层的最先进行修饰,最内层的是最后进行修饰的

那么变体还有那些呢,还有最后一个

带参装饰器

def godme(message):    print(message)    def __godme(fun):        print('__godme')        return fun    return __godme@godme('messahe')def test():    print('test')test()'''messahe__godmetest'''
哈哈,装饰器也可以传入参数了,为什么呢

仔细探究一下,符号装饰不过是指明了一个装饰器对象而已,在括号调用的时候其实已经执行过这个方法了

只要符号后面跟的是一个单参或多参单非默认入参的装饰器就行了

于是我接下来做了这么两件事

def godme(mark):    def __one(fun):        print('one')        return fun    def __two(fun):        print('two')        return fun    if mark == 1:        return __one    if mark == 2:        return __two@godme(1)def test():    print('test')test()'''onetest'''
我擦,这不就是选择装饰器么,get了没

至于第二种,没有成功,下面是我的实验代码

def godme(mark):    print(mark)    def __one(info):        print(info)        def __two(fun):            print('two')            return fun        return __two    return __one@godme('zero')('one')def test():    print('test')test()
是不支持这种呢,还是我的见识短浅呢,希望有答案的朋友教教我


装饰器的基本变体就是这么多了,更多深入的操作在后面讲述







原创粉丝点击