python装饰器

python装饰器,第1张

python装饰器 闭包

装饰器的基础就是闭包。闭包首先是嵌套函数,并且内层函数对外层函数变量非全局变量有引用。

def wrap(x):
    def inner():
        print('start')
        print(x)
        print('end')
    return  inner

_inner = wrap(2)
_inner()

_inner得到了内层函数的内存地址,形参x就是外层函数的变量。闭包的一个特性就是外层函数结束了,内存函数依然可以被调用。

装饰器

装饰器从字面意思上理解就是装饰用的,在python中就是给原函数加功能的,相当于装饰。在给函数加功能的时候不改变被装饰函数的代码和调用方式。在游戏中,有一个打的功能,需要给打的功能增加一个击退效果。用这个简单模拟下装饰器的使用方式。
被装饰函数:

def attack():
    print('这里是打,就是这么简单')
attack()

版本一:

def attack():
    print('这里是打,就是这么简单')
    print('这里是击退')

attack()

#代码执行效果
这里是打,就是这么简单
这里是击退

版本一,能实现这个效果,但是它改变了原函数的代码,新增了一行打的代码,不符合装饰器的要求。
版本二:

def attack():
    print('这里是打,就是这么简单')


def wrap(x):
    def inner():
        x()
        print('这里是击退')
    return inner

_attack = wrap(attack)  #这里_attack可以取名为attack
_attack()               #同样可以attack调用

#执行效果
这里是打,就是这么简单
这里是击退

版本二应用了闭包,将被装饰函数当作参数传入内层函数调用。被装饰函数attack内部代码没有被改变,同样实现了效果。但是这里函数的调用改变了,原来attack()变成了_attack()。
是的,我们取名字的时候可以_attack()变成attack()不就行了。这样又不改变被装饰函数,又不改变调用方式。这就是一个装饰器。attack = wrap(attack)可以用@wrap表示,@加上装饰器函数名。@wrap一定要在被装饰函数的上面连在一起。哪个函数,比如闪现需要击退,就在闪现函数的上面加这一行就可以实现闪现击退效果。

def wrap(x):
    def inner():
        x()
        print('这里是击退')
    return inner

@wrap   #attack = wrap(attack)   
def attack():
    print('这里是打,就是这么简单')

attack()

#执行效果
这里是打,就是这么简单
这里是击退

算是完成了一个装饰器。但是attack函数是没有任何返回值和参数的,那带有返回值和参数的怎么装饰呢
版本三:装饰带返回值的函数,假入attack()函数每次打都会返回一个True,:

def attack():
    print('这里是打,就是这么简单')
    return True

带返回值装饰器:

def wrap(x):
    def inner():
        result = x()  #result得到了attack()的返回值True
        print('这里是击退')
        return  result  #返回True
    return inner

@wrap   #attack = wrap(attack)
def attack():
    print('这里是打,就是这么简单')
    return True   #被装饰器函数返回一个True

print(attack())  #这里attack得到的是inner函数的内存地址,所有attack()的返回值通过inner的返回值传回。

#执行结果
这里是打,就是这么简单
这里是击退
True  

上面已经实现了带返回值的装饰器。如果被装饰的函数带有参数呢,比如attack(a,b,c),并且击退效果不仅仅装饰打的动作,还可以装饰闪现功能,闪现功能的参数数量和attack的数量不一样,怎么装饰呢
版本四:带有参数的函数的装饰器

def wrap(x):
    def inner(*args,**kwargs):
        result = x(*args,**kwargs)
        print('这里是击退')
        return  result
    return inner

@wrap   #attack = wrap(attack)
def attack(name):                 #这里定义了需要传入一个参数
    print(f'这里{name}是打,就是这么简单')
    return True

attack('lg')   #这里lg被传给了inner函数,inner函数最终将lg转交给了上面的x(*args,**kwargs)

#执行结果
这里lg是打,就是这么简单
这里是击退

版本四就完成了一个可以装饰传入参数,也可以有返回值的装饰器。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5701341.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存