Python装饰器的使用

Python装饰器的理解


Python装饰器(Decorators)用于不改变函数源代码的基础上,对函数添加新的功能。可比如:人的衣服,不改动衣服原材料的情况下,可以在上面加个小红花之类的,哈哈。

装饰器可以作用在,平常购买商品时,点击购买会将购买商品的函数放入进去,如果是登录状态则可以执行这个函数,未登录的话,则跳转到登录界面,不执行购买函数。

在理解Python装饰器前得先理解一下闭包的概念:

博主写了一篇关于闭包的博客,可以参考一下:https://blog.csdn.net/m0_46958731/article/details/110336617


Python装饰器的使用

一个普通计算函数运行时间的装饰器

import time	# 记得导入这个时间模块

def run_time(func):	# 接收一个函数对象
    def wrapper(*args,**kyargs):	# 为了防止被装饰函数需要传参
        start = time.time()
        
        func(*args,**kyargs)	# 调用了传递进来的函数对象
        
        stop = time.time()
        print('run %s time is %0.2fs' % (func.__name__,stop - start))

    return wrapper # 调用run_time函数后,把wrapper装饰器函数返回给调用者

调用创建好的装饰器

# 定义一个函数,待会被装饰的就是它了
def index():
	print('my name is index')
	time.sleep(1)

test_index = run_time(index)	# 将index函数对象传递进去
# test_index = run_time(index) = wrapper
# 接收到run_time函数的返回值 wrapper的函数对象:test_index = wrapper

test_index()	# 调用 wrapper这个装饰器函数

执行效果:

'my name is index'
'run index time is 1.00s'

是不是感觉少了点啥,少了@装饰器语法糖的使用,但其实装饰器就是就一个方法,添加@只是少了一行传递被装饰函数的代码

未使用语法糖前
test_index = run_time(index)
# 只是可以自定义变量名,也可以将变量名定义成index
test_index()

使用语法糖以后:把调用代码化简,放在被装饰函数的上方即可
@run_time	# run_time(index)
def index():
	print('my name is index')
	
index()	# 可以调用装饰好以后index函数了

调用结果:

'my name is index'
'run index time is 1.00s'

@语法只是将被装饰函数传递到装饰器函数,与未使用@时调用结果一样


装饰器处理被装饰函数的返回值

相同的代码,处理计算的功能

装饰器写法,几乎没有区别,加入return只是被装饰函数会有返回值

def calculation(func):  # 接收一个函数对象
    def wrapper(*args, **kyargs):  # 为了防止被装饰函数需要传参

        print('装饰器将 %s 传递给了 %s 函数' % (args,func.__name__))
        res = func(*args, **kyargs)  # 将传递给wrapper函数的值交函数对象,这里就是交给下面index函数了
        # res拿到index函数的返回值

        return res  # 将得到的值返回给调用者

    return wrapper  # 调用run_time函数后,把wrapper装饰器函数返回给调用者

被装饰函数

@calculation
def index(x,y):
    print('index接收到了 %s %s 参数' % (x,y))
    return x + y   # 当调用到index时,返回x+y的处理结果



# 注意:这个index并不是代表上面index函数,因为经历了:index = calculation(index) 将index函数作为对象传递进去
# 然后这个index变量 拿到wrapper的返回对象了,然后index = wraper
# 理解为:index = calculation(index) = wrapper

print('拿到装饰器的返回值:',index(1,10))	# 调用wrapper装饰器函数,并向它传递两个值

执行效果:

'装饰器将 (1, 10) 传递给了 index 函数'
'index接收到了 1 10 参数'
'拿到装饰器的返回值了: 11'

带参数的装饰器

装饰器可以携带参数传入,一个携带参数的装饰器有三层

def outter(parameter): # 接收被调用时传递的参数
    print('装饰器接收到的一个参数:',parameter)
    def decorators(func):
        def wrapper(*args,**kwargs):
            func(*args,**kwargs)

        return wrapper

    return decorators # 将装饰器函数对象,返回给调用者

# 在@语法调用装饰器时,给它传递了一个参数
@outter("this is decorators parameter")
def index():
    print('my name is index')

index()

打印结果:
'装饰器接收到的一个参数: this is decorators parameter'
'my name is index'

或许这样看会有些迷惑,但我们恢复成不用@语法就能通俗易懂了

outter = outter('this is decorators parameter')
# 调用装饰器外层函数,传递一个参数进去,然后它返回了装饰器decorators的函数对象

index = outter(index) # 哈哈,又变成了和上序一样的写法, index = outter(index) = wrapper
index() # 调用wrapper装饰函数

到此为止,装饰器也并没有想象中的那么复杂。

装饰器语法体现了函数作为Python中的一等公民,可以是对象,变量,也可以作为参数和返回值,说明了Python函数的强大与灵活。

技术小白记录学习过程,有错误或不解的地方请指出,如果这篇文章对你有所帮助请点赞 收藏+关注 谢谢支持!

上一篇:as4.1设置读取本地gradle(as项目报Could not install Gradle distribution from ‘https://services.gradle.org错误)


下一篇:Angular jasmine单元测试框架spied method的调用记录数据结构