Python札记 -- 装饰器补充

本随笔是对Python札记 -- 装饰器的一些补充。

使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码:

 1 #!/usr/bin/env python
 2
 3 def deco(func):
 4     def wrapper():
 5         print "Wrap start"
 6         func()
 7         print "Wrap end\n"
 8     return wrapper
 9
10 @deco
11 def foo():
12     """Docstring for foo"""
13     print "In foo():"
14
15 foo()
16 print foo.__name__
17 print foo.__doc__

输出如下:

$ python decorator_test.py
Wrap start
In foo():
Wrap end

wrapper
None

可以发现,__name__属性成了wrapper,而__doc__属性则成了None。这对于平常使用多少带来些不便,总不能给每个使用装饰器的函数都重写__name__和__doc__吧。

Python的functools提供的update_wrapper和wraps可以有效解决这个问题。不过update_wrapper是用方法的形式进行调用,而wraps则是用装饰器来封装了update_wrapper。示例代码分别如下:

 1 #!/usr/bin/env python
 2 from functools import update_wrapper
 3
 4 def deco(func):
 5     def wrapper():
 6         print "Wrap start"
 7         func()
 8         print "Wrap end\n"
 9     return update_wrapper(wrapper,func) #调用update_wrapper方法
10
11 @deco
12 def foo():
13     """Docstring for foo"""
14     print "In foo():"
15
16 foo()
17 print foo.__name__
18 print foo.__doc__
 1 #!/usr/bin/env python
 2 from functools import wraps
 3
 4 def deco(func):
 5     @wraps(func) #使用装饰器来实现
 6     def wrapper():
 7         print "Wrap start"
 8         func()
 9         print "Wrap end\n"
10     return wrapper
11
12 @deco
13 def foo():
14     """Docstring for foo"""
15     print "In foo():"
16
17 foo()
18 print foo.__name__
19 print foo.__doc__

现在被deco装饰过的foo方法,可以保留之前的__name__和__doc__属性了。

$ python decorator_test_with_update_wrapper.py
Wrap start
In foo():
Wrap end

foo
Docstring for foo

$ python decorator_test_with_wraps.py
Wrap start
In foo():
Wrap end

foo
Docstring for foo
时间: 2024-08-02 06:36:43

Python札记 -- 装饰器补充的相关文章

Python札记 -- 装饰器

这几天花了点时间了解了下 Python的装饰器.其实以前在书上也看过有关的内容,不过当时不理解.今天把自己的一点体会写出来跟大家分享一下. 网上流传得比较广的,有关 python装饰器的文章有两篇,一篇是 CSDN上的,另外一篇是园子里的.附带链接如下:     http://blog.csdn.net/thy38/article/details/4471421     http://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html    

【转】详解Python的装饰器

原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def say_hello(): print "hello!" def say_goodbye(): print "hello!" # bug here if __name__ == '__main__':

详解Python的装饰器

Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def say_hello(): print "hello!" def say_goodbye(): print "hello!" # bug here if __name__ == '__main__': say_hello() say_goodbye() 但是在实际调用中,我们

尝试自己的Perl语言的包 TCP协议的再包装起到类似python语言装饰器的效果

#!/usr/bin/perl # Filename: BuildSocketTCP.pm # #   Copyright 2012 Axxeo GmbH #   Licensed under the Apache License, Version 2.0 (the "License"); #   you may not use this file except in compliance with the License. #   You may obtain a copy of t

尝试自己的Perl语言的包 UDP协议的再包装起到类似python语言装饰器的效果

#!/usr/bin/perl # Filename: BuildSocketUDP.pm # #   Copyright 2012 Axxeo GmbH #   Licensed under the Apache License, Version 2.0 (the "License"); #   you may not use this file except in compliance with the License. #   You may obtain a copy of t

python函数装饰器

学习装饰器前提需要了解高阶函数,函数嵌套,函数闭包 python函数装饰器,顾名思义就是装饰函数,为函数添加新功能的的一种方式. 为什么要使用装饰器呢? 因为函数在运行时,如果不使用装饰器对函数进行功能添加,需要修改函数源代码,这样修改无疑会增加程序的冗余和复杂性,也不便于程序员对其进行修改.使用装饰器,可以在不改变函数源代码和调用方式的前提下,使用语法糖@装饰器,对函数功能进行添加. 装饰器本质上就是一个函数. 我们使用一个简单的例子来实现: import time #这是一个装饰器函数名为t

Python之装饰器、迭代器和生成器

在学习python的时候,三大“名器”对没有其他语言编程经验的人来说,应该算是一个小难点,本次博客就博主自己对装饰器.迭代器和生成器理解进行解释. 为什么要使用装饰器 什么是装饰器?“装饰”从字面意思来谁就是对特定的建筑物内按照一定的思路和风格进行美化的一种行为,所谓“器”就是工具,对于python来说装饰器就是能够在不修改原始的代码情况下给其添加新的功能,比如一款软件上线之后,我们需要在不修改源代码和不修改被调用的方式的情况下还能为期添加新的功能,在python种就可以用装饰器来实现,同样在写

python之-- 装饰器

高阶函数+嵌套函数 == 装饰器 什么是装饰器: 其实也是一个函数. 功能:为其他的函数添加附加功能 原则:不能修改被装饰的函数的源代码和调用方式 学习装饰器前首先要明白以下3条事项: 1:函数 即 "变量" (什么意思呢,就是说我们定义的一个函数,其中函数名就是一个变量,函数体就是存于内存的数据). def foo(): #函数名就相当于变量 print('test') #函数体就相当于内容 类似于:x(变量) = 1(内容) 内容实际存储于内存,变量相当于门牌号(映射内存内容).

python之装饰器 实例

=====================================写法1========================== import time def timer(func):     def deco():         start_time = time.time()         func()         stop_time = time.time()         print('the func run time is %s' %(stop_time - star