栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

函数5:装饰器

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

函数5:装饰器

目录

1. 装饰器基础

2. 装饰器编码

3. @修饰符

4. 多层装饰器


1. 装饰器基础

返回值为另一个函数的函数,通常使用 @wrapper 语法形式来进行函数变换。 装饰器的常见例子包括 classmethod() 和 staticmethod()。

装饰器语法只是一种语法糖,以下两个函数定义在语义上完全等价:

def f(arg):
    ...
f = staticmethod(f)

@staticmethod
def f(arg):
    ...

2. 装饰器编码

Python中,装饰器(decorator)的功能是将被装饰的函数当做参数传递给与装饰器对应的函数(名称相同的函数),并返回包装后的被装饰的函数。

装饰器是为了解决新增功能、修改函数时,不要修改原代码、增加复杂逻辑的需求而出现的;

通过闭包实现新功能,同时将原函数作为外部函数参数调用,并将原函数重新声明为闭包返回结果,这样原函数作为外部作用域不被修改,同时重新声明的原函数通过闭包实现新功能;

如下示例中,按装饰器编码思路如下:

  1. 初始函数为 test() ,要给 test() 新增注释功能,但不想修改 test() 代码;
  2. 新增 log() 作为装饰器,以 funx 作为形参,并在闭包内部函数 closure_test 中增加需要新增的注释功能,并调用 funx() ;
  3. 将初始函数 test 作为参数传递给装饰器 log() ,同时赋值给初始函数同名 test 为新函数;
  4. 初始函数 test() 作为装饰器外部作用域实参,保持不变,不被新赋值的同名 test() 函数修改;
  5. 新赋值函数 test() 则赋值为装饰器返回结果,调用未被修改的初始函数 test() ,并实现了需要的注释功能。
def log(funx):
    def closure_test():
        print(f'开始函数{funx.__name__}调用!')
        funx()
        print(f'结束函数{funx.__name__}调用!')
    return closure_test

def test():
    print('开始测试~~~')

test = log(test)
test()

开始函数test调用!
开始测试~~~
结束函数test调用!

3. @修饰符

上一章节中test = log(test) 有更简洁的表达方法,即应用@修饰符形成的“@语法糖”来解决这个问题,把“@修饰符+装饰器”,置于被修饰的原函数之前;

上一章节代码可以按如下形式编写:

def log(funx):
    def closure_test():
        print(f'开始函数{funx.__name__}调用!')
        funx()
        print(f'结束函数{funx.__name__}调用!')
    return closure_test

@log
def test():
    print('开始测试~~~')

test()

开始函数test调用!
开始测试~~~
结束函数test调用!

如果原函数 test() 有参数,则装饰器内部函数也添加参数,并将该参数录入内部函数中被调用的初始函数,实现如下:

def log(funx):
    def closure_test(testname):
        print(f'开始函数{funx.__name__}调用!')
        funx(testname)
        print(f'结束函数{funx.__name__}调用!')
    return closure_test

@log
def test(testname):
    print(f'开始测试{testname}~~~')

test('CS 1.6')

开始函数test调用!
开始测试CS 1.6~~~
结束函数test调用!

为了防止初始函数 test() 后续修改形参数量,可以装饰器内部函数参数设计为收集参数-元组,如下:

def log(funx):
    def closure_test(*testname):
        print(f'开始函数{funx.__name__}调用!')
        funx(*testname)
        print(f'结束函数{funx.__name__}调用!')
    return closure_test

@log
def test(var1,var2):
    print(f'开始测试{var1},{var2}~~~')

test('DOTA','LOL')

开始函数test调用!
开始测试DOTA,LOL~~~
结束函数test调用!

4. 多层装饰器

Python也支持装饰器多层嵌套;

多个@装饰器上下排列,相当于从上至下从最外层到最内层嵌套函数,示例如下:

#三个装饰器
def addone(funx):
    def closure_test(*input):
        x = funx(*input)
        return x + 1
    return closure_test

def reducetwo(funx):
    def closure_test(*input):
        x = funx(*input)
        return x - 2
    return closure_test

def square(funx):
    def closure_test(*input):
        x = funx(*input)
        return x * x
    return closure_test

#不使用@修饰符,直接做多重函数嵌套
def test1(numble):
    return numble

test1 = square(reducetwo(addone(test1)))

print(test1(5))

#使用@修饰符,做多重装饰器
@square
@reducetwo
@addone
def test2(numble):
    return numble

print(test2(5))

#返回结果一致
16
16

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/984107.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号