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 条评论
登录 后参与评论

相关文章

来自专栏开发与安全

虚析构函数? vptr? 指针偏移?多态数组? delete 基类指针 内存泄漏?崩溃?

五条基本规则: 1、如果基类已经插入了vptr, 则派生类将继承和重用该vptr。vptr(一般在对象内存模型的顶部)必须随着对象类型的变化而不断地改变它的指向...

2240
来自专栏程序员互动联盟

【编程基础】如何赢得C++面试

1.new、delete、malloc、free关系 delete会调用对象的析构函数,和new对应的是free,free只会释放内存,new调用构造函数。m...

3777
来自专栏小狼的世界

Python 3.6学习笔记(一)

可以看到,注释以#开头,python的变量不需要任何前缀,行结束不需要结束符号,非常符合我们自然语言的阅读和书写习惯。当语句以:结尾时,缩紧的语句视为代码块。

932
来自专栏我的技术专栏

C++ 异常机制分析

1314
来自专栏程序员的知识天地

Python编程入门基础语法详解经典

sample_nest = [(2,4,6),{5:7,9:11,'key':[2,5]},6]

861
来自专栏破晓之歌

JAVA入门1 原

下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk9-downloads-3848...

1152
来自专栏debugeeker的专栏

《coredump问题原理探究》Linux x86版6.8节多继承coredump例子

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xuzhina/article/detai...

602
来自专栏猿人谷

C++ 模板学习

1. 模板的概念。 我们已经学过重载(Overloading),对重载函数而言,C++的检查机制能通过函数参数的不同及所属类的不同。正确的调用重载函数。例如,为...

23110
来自专栏猿人谷

【Objective-C】05-第一个OC的类

说明:这个Objective-C专题,是学习iOS开发的前奏,也为了让有面向对象语言开发经验的程序员,能够快速上手Objective-C。如果你还没有编程经验,...

21510
来自专栏编程

《4》python数据类型和变量

(4)python数据类型和变量 ? 整数 Python可以处理任意大小的整数,例如:1,100,-8080,0,等等。 十六进制用0x前缀和0-9,a-f表示...

3369

扫码关注云+社区