前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python 装饰器

python 装饰器

作者头像
py3study
发布2018-08-02 15:53:40
4210
发布2018-08-02 15:53:40
举报
文章被收录于专栏:python3python3

装饰器本质上是一个Python函数,它可以让其他函数在不雲要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。

它经常用于有切面雲求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。

装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大畺与函数功能本身无关的雷同代码并继续重用。

概括的讲,装饰器的作用就是为已经存在的对象添加颉外的功能。

定义:

本质是函数,装饰器他函数,为器他函数添加附加功能。

原则:

不能修改被装饰函数的源代码

不能修改被装饰函数的调用方法

总结:

装饰器对被装饰的函数,是完全透明的,没有任何影响。

举个例子:

下面有一个函数,需要加一个功能,打印程序执行的时间

代码语言:javascript
复制
import time
def test1():
    #等待1秒,表示代码逻辑部分,这里直接简写了
    time.sleep(1)
    print('in the test1')

这个函数已经上线很久了,如果更改源代码,是有风险的。

这个时候,用装饰器,就可以解决这个问题。

代码语言:javascript
复制
import time
def timmer(func):
    def warpper(*args,**kwargs):
        start_time = time.time()
        func()
        stop_time = time.time()
        print('the func run time is %s' %(stop_time - start_time))
    return warpper

@timmer
def test1():
    time.sleep(1)
    print('in the test1')

test1()

执行输出

in the test1

the func run time is 1.0007095336914062

首先需要写一个装饰器函数,在被装饰的函数名上一行,加@装饰器函数名,就可以了

实现装饰器知识储备:

1.函数即"变量"

2.高级函数

  a.把一个函数名当作实参传给另外一个函数(不修改被装饰函数的源代码前提下,为其添加功能)

  b.返回值中包含函数名(不修改函数的调用方式)

3.嵌套函数

高阶函数+嵌套函数 = 装饰器

代码语言:javascript
复制
def bar():
    print('in the bar')

def test1(func):
    print(func)

test1(bar)

执行输出

得到的结果是一个内存地址。

代码语言:javascript
复制
def bar():
    print('in the bar')

def test1(func):
    print(func)
    func()

test1(bar)

执行输出

in the bar

func执行,得到一个内存地址,因为它是一个变量,函数即变量

func()执行,就是把内存地址的内容调取出来,得到in the bar

代码语言:javascript
复制
import time
def bar():
    time.sleep(1)
    print('in the bar')

def test1(func):
    start_time = time.time()
    #执行bar()函数
    func()
    stop_time = time.time()
    print('the func run time is %s' % (stop_time - start_time))

test1(bar)

执行输出

in the bar

the func run time is 1.000032901763916

test1(bar)执行的时候,把bar函数传进去了

那么test1函数体内的func就等同于bar函数

所以程序执行,输出了上面2行的结果。

上面的代码,貌似实现了装饰器的功能。源代码bar,并没有修改啊,但是违背了第2个原则,修改了函数的调用方法。

默认bar函数调用时,直接bar()就可以了,现在变成了test1(bar)。

代码语言:javascript
复制
import time
def bar():
    time.sleep(1)
    print('in the bar')

def test2(func):
    print(func)
    return func

print(test2(bar))

执行输出

function bar at 0x0000017DFD6E3E18

function bar at 0x0000017DFD6E3E18

返回的结果是一个内存地址

把执行方式改一下

代码语言:javascript
复制
t = test2(bar)
print(t)

执行输出

function bar at 0x0000017DFD6E3E18

in the bar

貌似没什么卵用

再改一下

代码语言:javascript
复制
t = test2(bar)
t()

执行输出

function bar at 0x0000017DFD6E3E18

in the bar

t()相当于执行了bar函数,貌似没啥卵用

再改一下

代码语言:javascript
复制
bar = test2(bar)
bar()

执行输出

function bar at 0x0000017DFD6E3E18

in the bar

结果和上面是一样的,但是调用方式,发现和原函数调用是一模一样的。

下面打印一下bar的类型是变量还是函数

代码语言:javascript
复制
bar = test2(bar)
print(type(bar))
bar()

执行输出

blob.png
blob.png

可以看出,bar赋值之后,变成了函数,为什么呢?因为test2本身就是函数,所以它当然是函数了。

所以才可以执行bar()

但是bar()已经不是原来的bar函数了,而是被装饰过的函数。

因为原来的bar执行,只会输出 in the bar

函数嵌套

定义:在一个函数中定义了另外一个函数

在一个函数体内,用def去声明一个新的函数,而不是去调用它。

下面是一个嵌套函数

代码语言:javascript
复制
def foo():
    print('in the foo')
    def bar():
        print('in the bar')

    bar()

foo()

执行输出

in the foo

in the bar

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-02-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档