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. 【bbs】login.php

    require的路径 整体结构的复用 渐变效果的加入 按钮:实现背景透明,文字不透明:在background-color中使用rgba,标准浏览器中,背景透明,文字不透明background-colo ...

  2. Centos 7下Nagios的安装及配置

    简介 Nagios 是一款自动化运维工具,可以协助运维人员监控服务器的运行状况,并且拥有报警功能.本文章将介绍其安装方法和详细的配置方法. nagios 监控服务应用指南 本地资源:负载,CPU,磁盘 ...

  3. Java 深入理解内部类

    摘自海子:Java内部类详解 深入理解内部类 1.为什么成员内部类可以无条件访问外部类的成员? 在此之前,我们已经讨论过了成员内部类可以无条件访问外部类的成员,那具体究竟是如何实现的呢?下面通过反编译 ...

  4. 轻量ORM-SqlRepoEx (十五)最佳实践之数据映射(Map)

    简介:SqlRepoEx是 .Net平台下兼容.NET Standard 2.0人一个轻型的ORM.解决了Lambda转Sql语句这一难题,SqlRepoEx使用的是Lambda表达式,所以,对c#程 ...

  5. Spring Cloud(四):服务容错保护 Hystrix【Finchley 版】

    Spring Cloud(四):服务容错保护 Hystrix[Finchley 版]  发表于 2018-04-15 |  更新于 2018-05-07 |  分布式系统中经常会出现某个基础服务不可用 ...

  6. oracle10g学习笔记

    1.简介 1.1.sql:Structured Query Language 结构化查询语言 1.2.windows在目录路径中使用反斜线\,unix和linux使用正斜线/ 1.3.Number(a ...

  7. 网络的可靠性nyoj170

    网络的可靠性 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 A公司是全球依靠的互联网解决方案提供商,也是2010年世博会的高级赞助商.它将提供先进的网络协作技术,展 ...

  8. 从Windows复制文件到Linux

    PuTTY自带的pscp非常好用. 使用方式和Linux中的scp命令很像,格式如下: pscp 文件 用户名@LinuxIP:目录 例如: pscp d:/a.iso root@192.168.1. ...

  9. php 实现重定向的三种方式

    header()函数; header('location:http://www.baidu.com'); meta标签; echo '<meta http-equiv="refresh ...

  10. 大数据学习--day12(内部类)

    内部类学习     定义在类的内部的类  叫做内部类     包含了内部类的类 叫做外部类 内部类的作用      内部类是为了 实现 java中 多继承而存在的      内部类 可以继承其他类   ...