Python的装饰器的概念,一直有点微妙。之前在StackOverflow上看过一篇感觉说明的很清楚的介绍:

*A decorator must accept a function as an argument
 
参考地址:
 
Objects are data with methods attached, closures are functions with data attached.
 
英文水平有限,对于这句话我的理解一直是这样:
 def a(fn):
print "function a"
def tmpfun(*args):
print "tmpfunc"
fu(*args)
return tmpfun @a
def b(*args):
print "function b" + str(args)

此时,调用b(1, 2)等效于a(b(1, 2)),编译器解析代码时,会先执行b,然后执行a。

今天遇到有人问类似的问题,试着写了一下,发现等效方法运行出错。
经过实验,发现用装饰器修饰的b函数调用时,b(1, 2)等效于a(b)(1, 2)。
装饰器函数需要的参数应该是被修饰的函数对象,而不是被修饰函数对象的执行结果。
以下为验证代码:
 def addSpan(fn):
print "addSpan executed"
def n(*args):
print "spam, spam, spam"
return fn(*args)
return n @addSpan
def useful(a, b):
print a**2 + b**2 def synonym(a, b):
print a**2 + b**2 if __name__ == '__main__':
useful(3, 4)
addSpan(synonym)(3, 4)

执行结果为:

addSpan executed
spam, spam, spam
25
addSpan executed
spam, spam, spam
25
[Finished in 0.1s]

可以看出虽然形式上被修饰的函数会先被执行,但是实际执行时,仍然是以装饰器函数为入口开始执行的。

反思:

作为装饰器的函数必须接收参数,而且必须返回可执行的函数对象,否则将出错:

def a():
print "function a" @a
def b():
print "function b" b()

运行结果:

Traceback (most recent call last):
File "/Users/.../decorator_test1.py", line 18, in <module>
@a
TypeError: a() takes no arguments (1 given)
[Finished in 0.1s with exit code 1]

如果装饰器函数声明了参数,但是没有声明返回对象,或者声明的返回对象是不可被调用的对象,同样会出错:

def a(fn):
print "function a" // 没有声明返回对象 @a
def b():
print "function b" b()

执行结果:

Traceback (most recent call last):
File "/Users/.../decorator_test1.py", line 27, in <module>
function a
b()
TypeError: 'NoneType' object is not callable
[Finished in 0.1s with exit code 1]

可以看到后续动作将None作为返回对象继续执行,然后出错。

或者:

def a(fn):
print "function a"
return "asd" // 声明返回对象为不可被调用的类型 @a
def b():
print "function b" b()

运行结果:

function a
Traceback (most recent call last):
File "/Users/.../decorator_test1.py", line 28, in <module>
b()
TypeError: 'str' object is not callable
[Finished in 0.1s with exit code 1]

正常运行结果:

def a(fn):
print "function a"
return fn // 返回参数获得的函数对象 @a
def b():
print "function b" b()

运行结果:

function a
function b
[Finished in 0.1s]

关于装饰器还有一些疑问,将在第二篇进行验证。

最新文章

  1. C#,.Net 学习资源
  2. Duilib源码分析(二)控件构造器—CDialogBuilder
  3. Mac中安装Vim7.4
  4. myeclipse优化
  5. split() 注意事项.
  6. MyCat 学习笔记 第八篇.数据分片 之 求摸运算分片
  7. lz4,pigz,gzip 3者比较
  8. WIN7 X64 如何运行debug
  9. MySQL存储引擎 InnoDB/ MyISAM/ MERGE/ BDB 的区别
  10. xml 解析 Xstream
  11. Haskell 笔记(三)类型系统
  12. Linux 查看CPU温度
  13. 《Linux就该这么学》第十七天课程
  14. 如何使用命令从linux服务器下载文件到windows
  15. Atitit 如何创新 创新只有在两种条件下发生:自由、效率。
  16. 062 hive中的常用方法(case,cast,unix_timestamp)
  17. iOS自定义结构体
  18. gets函数
  19. 黄聪:ffmpeg基本用法(转)
  20. Python 装饰器入门(下)

热门文章

  1. 数论——算数基本定理 - HDU 4497 GCD and LCM
  2. programming-languages学习笔记--第4部分
  3. 【Git】常见错误提示解决办法和常用方法
  4. 剑指offer 最小的k个数 、 leetcode 215. Kth Largest Element in an Array 、295. Find Median from Data Stream(剑指 数据流中位数)
  5. (转)进程process和线程thread的关系
  6. spring cloud各个模块作用
  7. Intellij IDEA 2018.2.2 SpringBoot热启动 (Maven)
  8. EF Core中如何正确地设置两张表之间的关联关系
  9. EF Core中外键关系的DeleteBehavior介绍(转自MSDN)
  10. ORA-00600:internal error code,arguments:[keltnfy-idmlnit],[46],[1],[],[],[],[],[]