python中的装饰器

很多时候我们可能会有这样的需求,就是在调试的时候我们会想打印出某些变量出来看看程序对不对,然后在我们调试好了的时候再把这些print语句注释;这样做确实比较麻烦,我们在想有没有简单的方法:就是在需要打印的时候加上,同时不改变函数的内部代码

其实这就是装饰器的思想了:

decorators work as wrappers, modifying the behavior of the code before and after a target function execution, without the need to modify the function itself, augmenting the original functionality, thus decorating it.

函数

先从函数开始说起,python中函数常见的有如下几种用法:

1 把函数赋值给一个变量 2 在函数中定义函数 3 函数可以作为另外一个函数的参数 4 函数可以返回一个函数

2、4比较常见,1、3相对较少见,看下例子:

def hello(name):
    return "hello," + name
hello_fn = hello
print(hello_fn("world"))
#outputs:
hello,world
def wrapper(func):
    name = 'john'
    return func(name)
print(wrapper(hello))
#outputs: 
hello,john

从第二个例子中其实就有点decorator的意思了,要实现之前说的那个功能我们现在可以这样:

def logging(func,*args, **kwargs):
     print('start logging...')
     res=func(*args,**kwargs)
     print('res=%s'%res)
     print('end logging')
     return res
logging(hello)
#outputs: 
start logging...
res=hello,name
end logging

貌似还可以,但是其实还有更简单的做法,就是decorator. 用法很简单就是个语法糖,比如现在需要在四则运算开始前打印’start logging’,在运算之后打印’logging end’,可以先定义个logging函数实现打印的功能:

def logging(func):
    def wrapper(*args, **kwargs):
        print('start logging...')
        res = func(*args, **kwargs)
        print('res=%d' % res)
        print('logging end.')
        return res
    return wrapper

接下来只要再调用,使用@就可以加上logging的功能

@logging
def add(x, y):
    return x+y
add(3,4)
#outputs:
start logging...
res=7
logging end.

假设你还想把运算的结果变成平方,可以再写个函数:

def square_res(func):
    def transfer(*args, **kwargs):
        print('square res...')
        res = func(*args, **kwargs)**2
        print('square end.')
        return res
    return transfer

加下来调用就好:

@logging
@square_res
def add(x, y):
    return x+y
add(3,4)
#outputs:
start logging...
square res...
square end.
res=49
logging end.

注意这里的顺序,先是square_res后是logging,@的写法刚好是相反的

写的很简单,也不太具体,只是想表达最简洁的意思和用法,想要了解的更具体的可以看:

  1. http://www.jianshu.com/p/1ae551fb17cd
  2. https://www.thecodeship.com/patterns/guide-to-python-function-decorators/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏编程

Python函数

今天是节后第一天上班,也是2018新的开始,首先祝各位新年快乐,学业有成,工作顺利,一切顺顺顺 今天我们来了解python中的函数 ? Python函数 函数是...

1699
来自专栏desperate633

LeetCode 22. Generate Parentheses题目分析代码

给定 n 对括号,请写一个函数以将其生成新的括号组合,并返回所有组合结果。 样例 给定 n = 3, 可生成的组合如下: "((()))", "(()()...

673
来自专栏和蔼的张星的图像处理专栏

14. 二分查找

给定一个排序的整数数组(升序)和一个要查找的整数target,用O(logn)的时间查找到target第一次出现的下标(从0开始),如果target不存在于数组...

792
来自专栏林德熙的博客

C# 传入 params object 长度

刚刚 LiesAuer 大神问了一个问题,如果在 params object 传入 object 数组,那么拿到的值是的长度是多少 我做了测试在传入不同的值可能...

572
来自专栏mathor

二分查找与二分答案(2)

1254
来自专栏后端技术探索

当一只程序员遇到了一道无聊的智力填数题!

本猿在朋友圈和群里多次看到这样一道智力题(见下图),一看就是一道需要乱扯的无聊的题目。好吧,试试就试试。

621
来自专栏技术/开源

一道javascript面试题

下面表达式比较的结果分别是什么? 1. []=="0" 2. []==0 3. "0"==0 4. []==false 5. []==[] 大家可以...

19910
来自专栏Python小屋

Python从序列中选择k个不重复元素

集合中的元素不允许重复,Python集合的内部实现为此做了大量相应的优化,判断集合中是否包含某元素时比列表速度快很多。下面的代码用于返回指定范围内一定数量的不重...

3036
来自专栏C/C++基础

抛出和接收异常的顺序

异常(exception)是C++语言引入的错误处理机制。它 采用了统一的方式对程序的运行时错误进行处理,具有标准化、安全和高效的特点。C++为了实现异常处理,...

813
来自专栏前端架构与工程

JavaScript几个作用域问题

1、 var a = 0 ; function f(){ a = 1; console.log(a); //全局变量a } console.log(a...

1736

扫码关注云+社区