关于Python的装饰器(1)
2024-08-29 19:34:17
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]
关于装饰器还有一些疑问,将在第二篇进行验证。
最新文章
- C#,.Net 学习资源
- Duilib源码分析(二)控件构造器—CDialogBuilder
- Mac中安装Vim7.4
- myeclipse优化
- split() 注意事项.
- MyCat 学习笔记 第八篇.数据分片 之 求摸运算分片
- lz4,pigz,gzip 3者比较
- WIN7 X64 如何运行debug
- MySQL存储引擎 InnoDB/ MyISAM/ MERGE/ BDB 的区别
- xml 解析 Xstream
- Haskell 笔记(三)类型系统
- Linux 查看CPU温度
- 《Linux就该这么学》第十七天课程
- 如何使用命令从linux服务器下载文件到windows
- Atitit 如何创新 创新只有在两种条件下发生:自由、效率。
- 062 hive中的常用方法(case,cast,unix_timestamp)
- iOS自定义结构体
- gets函数
- 黄聪:ffmpeg基本用法(转)
- Python 装饰器入门(下)
热门文章
- 数论——算数基本定理 - HDU 4497 GCD and LCM
- programming-languages学习笔记--第4部分
- 【Git】常见错误提示解决办法和常用方法
- 剑指offer 最小的k个数 、 leetcode 215. Kth Largest Element in an Array 、295. Find Median from Data Stream(剑指 数据流中位数)
- (转)进程process和线程thread的关系
- spring cloud各个模块作用
- Intellij IDEA 2018.2.2 SpringBoot热启动 (Maven)
- EF Core中如何正确地设置两张表之间的关联关系
- EF Core中外键关系的DeleteBehavior介绍(转自MSDN)
- ORA-00600:internal error code,arguments:[keltnfy-idmlnit],[46],[1],[],[],[],[],[]