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]

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

关于Python的装饰器(1)的更多相关文章

  1. Python各式装饰器

    Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...

  2. Python札记 -- 装饰器补充

    本随笔是对Python札记 -- 装饰器的一些补充. 使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码: #!/usr/bin/env python def deco(func): def ...

  3. python基础——装饰器

    python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...

  4. 【转】详解Python的装饰器

    原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...

  5. 两个实用的Python的装饰器

    两个实用的Python的装饰器 超时函数 这个函数的作用在于可以给任意可能会hang住的函数添加超时功能,这个功能在编写外部API调用 .网络爬虫.数据库查询的时候特别有用 timeout装饰器的代码 ...

  6. python 基础——装饰器

    python 的装饰器,其实用到了以下几个语言特点: 1. 一切皆对象 2. 函数可以嵌套定义 3. 闭包,可以延长变量作用域 4. *args 和 **kwargs 可变参数 第1点,一切皆对象,包 ...

  7. 理解Python中的装饰器//这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档

    转自:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html 这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档 ...

  8. python基础—装饰器

    python基础-装饰器 定义:一个函数,可以接受一个函数作为参数,对该函数进行一些包装,不改变函数的本身. def foo(): return 123 a=foo(); b=foo; print(a ...

  9. 详解Python的装饰器

    Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...

  10. 关于python的装饰器(初解)

    在python中,装饰器(decorator)是一个主要的函数,在工作中,有了装饰器简直如虎添翼,许多公司面试题也会考装饰器,而装饰器的意思又很难让人理解. python中,装饰器是一个帮函数动态增加 ...

随机推荐

  1. Unity3D-制作火焰效果

    1.插件的准备 随着官网上的迭代更新,连下载按钮都找了好久,今天制作的火焰效果要依赖一个插件,LowPoly Environment Pack 输入网址unity3d.com在Assert Store ...

  2. maven 编译替换占位符

    首先开启资源配置的插件,由此插件替换占位符 <plugin> <groupId>org.apache.maven.plugins</groupId> <art ...

  3. PAT——1031. 查验身份证

    一个合法的身份证号码由17位地区.日期编号和顺序编号加1位校验码组成.校验码的计算规则如下: 首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8, ...

  4. 循环获取某个class下的多个select的选中值

    //循环获取某个class下的多个select的选中值 function eachSelect(cla){ var val = ""; $("."+cla).e ...

  5. cocos2d-x开发: 完善接口范例分离模块

    在上一篇文章中,我阐述了一下为什么要做分离这种工作,这篇文章没什么重点,只是将上一次没有完善的工作做完.原本我想做到像Lua-tests那样子,能够一次完全显示所有的tests,然后选择要执行的tes ...

  6. ios开发者较为好用的工具

    移动应用世界发生了巨大的变化,无论是在风格上还是在市场竞争上,消费者意识都推动了移动应用开发公司的崛起. 新的应用以及新的功能的出现 Apple IOS是为用户提供最新工具和升级的平台之一,它为iPh ...

  7. java核心技术-多线程之引导概念

    前两篇文章分别讲了,Java线程相关基础概念以及线程的内存模型,本节作为后续章节的引导,个人认为对于学习后面的只是还是比较重要.好了,既然说了多线程,那么首先要弄清以下几个问题: 1. 什么是多线程? ...

  8. javascript 中x++和++x的不同

    x++和++x都是给x加一,但是前者是完成赋值之后再递增x,后者相反. 例如:如果x是5,y=x++会将y设置为5,x设置为6:而y=++x会将x和y都设置为6.

  9. Fpm启动机制及流程分析———详细

    FPM(FastCGI Process Manager)是PHP FastCGI运行模式的一个进程管理器,从它的定义可以看出,FPM的核心功能是进程管理,那么它用来管理什么进程呢?这个问题就需要从Fa ...

  10. PTA基础编程题目集6-3简单求和 (函数题)

    6-3 简单求和 (10 分) 本题要求实现一个函数,求给定的N个整数的和. 函数接口定义: int Sum(int List[],int N) 其中给定整数存放在数组List[]中,正整数N是数组元 ...