python中的装饰器详解
admin
2023-07-31 02:14:28
0

在了解装饰器的之前一定要先了解函数作为参数传递, 什么是函数内嵌,请参考我之前写的博客函数简介

因为在python里面,函数也是对象,也可以作为参数进行传递.python装饰器本质也是一种特殊函数,它接收的参数是函数对象,然后动态地函数参数添加额外的功能,而不用修改原有的函数对象.python装饰器传入的参数是函数,返回的值也是函数!
python装饰器思想有点类似设计模式的装饰模式, 其意图是动态地给函数对象添加额外的功能.比如像增加日志打印的功能,有点面向切面编程(AOP)的感觉.
装饰器语法

以@开头,接着后面跟着的是装饰器的名字和可选的参数.装饰器语法是一种语法糖.
格式如下

复制代码 代码如下:
@decomaker(deco_args)
    def foo(func_opt_args)

可以组合,等价于foo = g(f(foo))
复制代码 代码如下:
@g
@f
def foo():
    statement

简单装饰器

实例

复制代码 代码如下:
#!/usr/bin/python
def  deco(func):
    print \’start\’
    func()
    print \’end\’
    return func

@deco
def foo():
    print \’In foo\’

foo()
foo()

输出
复制代码 代码如下:
start
In foo
end
In foo
In foo

带内嵌函数装饰器

内嵌函数保证每次新函数都被调用.而且被装饰的函数可以带有参数.
实例

复制代码 代码如下:
def  deco(func):
    def _deco(x):    #该函数为内嵌函数
        print \’start\’
        func(x)
        print \’end\’
    return _deco

@deco
def foo(x):
    print \’In foo, get value is: %d\’ % x

foo(123456)

输出:
复制代码 代码如下:
start
In foo, get value is: 123456
end

带参数的装饰器

需要自己返回以函数作为参数的装饰器。换句话说,decomaker()用 deco_args 做了些事并返回函数对象,而该函数对象正是以 foo 作为其参数的装饰器。简单的说来:foo=decomaker(deco_args)(foo)

实例

复制代码 代码如下:
def deco(arg):
    def wrapper1(func):
        def _deco(x):
            print \”get type is: \”, arg
            func(x)
        return _deco

    def wrapper2(func):
        def _deco(x):
            func(x)
            print \”get type is: \”, arg
        return _deco

    if arg == \’type1\’:
        return wrapper1
    else:
        return wrapper2

@deco(\”type2\”)
def foo(x):
    print \’In foo: \’, x

foo(123)

输出
复制代码 代码如下:
In foo:  123
get type is:  type2

总结

装饰器本质是高阶的函数,可以装饰其他函数,增加被装饰函数的功能,但不能覆盖或改变被装饰函数原有的行为.对于被装饰的函数来说,装饰器是透明的.装饰器传入参数为函数,返回的函数是被装饰的函数.最后我们来实现给一个函数添加打印日志的功能,而不用改变这个函数.

复制代码 代码如下:
#!/usr/bin/python
#coding=utf-8
import functools

def log(prefix, suffix):
    def deco(func):
        @functools.wraps(func)
        def wrapper(*args, **kargs):
            print \’%s log start\’ % prefix
            print(\’get a is: %s\’ % args[0])
            print(\’get b is: %s\’ % args[1])
            print(\’get c is: %s\’ % args[2])
            print(\’get d is: %s\’ % kargs[\’d\’])
            print(\’get d is: %s\’ % kargs[\’f\’])
            func(*args, **kargs)
            print \’%s log end\’ % suffix
        return wrapper
    return deco

@log(\’logstart\’, \’logend\’)
def test(a, b, c, d, f):
    print \’call func name is: %s\’ % test.__name__

test(1, 2, 3, d = \’dddd\’, f = \’ffff\’)

输出:
复制代码 代码如下:
logstart log start
get a is: 1
get b is: 2
get c is: 3
get d is: dddd
get d is: ffff
call func name is: test
logend log end

相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
项目管理和工程管理的区别 项目管理 项目管理,顾名思义就是专注于开发和完成项目的管理,以实现目标并满足成功标准和项目要求。 工...