上一篇文章开始的时候提到
   “一般来说,装饰器是一个函数,接受一个函数(或者类)作为参数,返回值也是也是一个函数(或者参数)”
  有一般情况,就有特殊情况。第一种特殊情况:装饰器可能也是一个类;第二种特殊情况:装饰器返回的对象的类型不一定等同于被装饰对象的类型。
 
  对于第一种情况,我们知道对于任何callable的对象都可以进行调用(在对象名称后面使用小括号),callable对象的范围就比较广了

(user-defined functions, built-in functions, methods of built-in objects, class objects, methods of class instances, and certain class instances themselves are callable; extensions may define additional callable object types).

  函数(方法)和类是callable,这个是很好理解的,如果一个类定义了__call__方法,那么该类的实例也是callable。另外,
     @dec
     def func():pass
  等价于: func = dec(func),所以如果dec是一个类,那么dec(func)是合理的,而被装饰后的func就变成了dec类的一个实例,如果dec类定义了__call__, 那么调用func(*)也是合理的,我们来看看修改后的代码
 class cost_time_logger(object):
def __init__(self, func):
self.func = func def __call__(self, *args, **kwargs):
import time
begin = time.time()
try:
return self.func(*args, **kwargs)
finally:
print('func %s cost %s' % (self.func.__name__, time.time() - begin)) @cost_time_logger
def complex_func(num):
ret = 0
for i in xrange(num):
ret += i * i
return ret if __name__ == '__main__':
print complex_func(100000)
  功能和上一篇文章的code snippet 0是一样的,但是type(complex_func) 变成了 <class '__main__.cost_time_logger'>,这也说明了第二种情况:被装饰的对象原本是函数,被装饰之后变成了一个类实例。
  在pep-0318中,例举了一个用装饰器实现单例的例子,代码如下
 def singleton(cls):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls()
return instances[cls]
return getinstance @singleton
class MyClass:
pass if __name__ == '__main__':
print type(MyClass)
  MyClass被装饰前是一个类,被装饰后变成了一个function。
 
  笔者不是很喜欢这种改变被装饰对象的类型的实现方法,这种实现对代码的阅读者不是很友好,而且可能产生一些莫名其妙的BUG,浪费debug的时间。对于单例的例子,stackoverflow上也有其他的实现。
 
references:

python decorator 进阶的更多相关文章

  1. Python Decorator 和函数式编程

    看到一篇翻译不错的文章,原文链接: Python Decorator 和函数式编程

  2. python最全学习资料:python基础进阶+人工智能+机器学习+神经网络(包括黑马程序员2017年12月python视频(百度云链接))

    首先用数据说话,看看资料大小,达到675G 承诺:真实资料.不加密,获取资料请加QQ:122317653 包含内容:1.python基础+进阶+应用项目实战 2.神经网络算法+python应用 3.人 ...

  3. python学习大全:python基础进阶+人工智能+机器学习+神经网络

    首先用数据说话,看看资料大小,达到675G承诺:真实资料.不加密.(鉴于太多朋友加我QQ,我无法及时回复,) 方便的朋友给我点赞.评论下,谢谢!(内容较大,多次保存) [hide]链接:[url]ht ...

  4. Python爬虫进阶四之PySpider的用法

    审时度势 PySpider 是一个我个人认为非常方便并且功能强大的爬虫框架,支持多线程爬取.JS动态解析,提供了可操作界面.出错重试.定时爬取等等的功能,使用非常人性化. 本篇内容通过跟我做一个好玩的 ...

  5. Python爬虫进阶五之多线程的用法

    前言 我们之前写的爬虫都是单个线程的?这怎么够?一旦一个地方卡到不动了,那不就永远等待下去了?为此我们可以使用多线程或者多进程来处理. 首先声明一点! 多线程和多进程是不一样的!一个是 thread ...

  6. Python爬虫进阶三之Scrapy框架安装配置

    初级的爬虫我们利用urllib和urllib2库以及正则表达式就可以完成了,不过还有更加强大的工具,爬虫框架Scrapy,这安装过程也是煞费苦心哪,在此整理如下. Windows 平台: 我的系统是 ...

  7. Python爬虫进阶一之爬虫框架概述

    综述 爬虫入门之后,我们有两条路可以走. 一个是继续深入学习,以及关于设计模式的一些知识,强化Python相关知识,自己动手造轮子,继续为自己的爬虫增加分布式,多线程等功能扩展.另一条路便是学习一些优 ...

  8. Python模块(进阶3)

    转载请标明出处: http://www.cnblogs.com/why168888/p/6411917.html 本文出自:[Edwin博客园] Python模块(进阶3) 1. python中模块和 ...

  9. Python面向对象进阶(二)

    Python面向对象进阶2.html :first-child{margin-top:0!important}img.plugin{box-shadow:0 1px 3px rgba(0,0,0,.1 ...

随机推荐

  1. SimpleMembership

    最近2个月以来,一直在学习MVC,从最开始的2,一直到最新的4.从原来的aspx到现在的Razor引擎,越学越开心,越学越上瘾. 最近为新项目做准备,打算用MVC4,VS2012+SQL2012,反正 ...

  2. Shiro SpringMVC 非maven HelloWorld

    项目用到Shiro就从网上找一些案例看看吧,结果看了很多都是maven的,没有办法就自己弄了一个.废话不多说,原理自己找开始上菜. 配置web.xml <?xml version="1 ...

  3. python3学习笔记(1)

    一.模块初识(接上篇)模块(库)分为两种:1.标准库:不需要安装直接可以导入的库,例:getpass.2.第三方库:必须要下载安装才可以使用.注:编辑的模块文件名不能与导入的模块名重复. 在模块文件中 ...

  4. python3学习笔记(0)

    一.编程语言主要从以下几个角度分类:1.编译型和解释型2.静态语言和动态语言3.强类型定义语言和弱类型定义语言编译型:程序运行前先由负责翻译的程序将代码转换成可执行代码进行执行.例如C/C++.Pas ...

  5. Ani动态光标格式解析

    数据结构: Ani文件中的数据是按区段存放的,区段数据结构如下: 标识符(4字节ASCII),数据长度(一个DWORD),数据 按照此规则来看Ani文件,文件起始12字节可以理解为标准文件头,除数据长 ...

  6. javascript常用的Math对象的方法

    简介 Math对象是在程序编程中用于执行一些数学任务的.Math 对象并不像 Date 和 String 那样是对象的类,因此没有构造函数 Math(),像 Math.sin() 这样的函数只是函数, ...

  7. Python函数篇

    1.函数名的命名规则: 函数名必须以下划线或字母开头,可以包含任意字母.数字或下划线的组合.不能使用任何的标点符号: 函数名是区分大小写的. 函数名不能是保留字. 2. 形参和实参 形参:形式参数,不 ...

  8. Python中的单例模式

    在 Python 中,我们可以用多种方法来实现单例模式: 使用模块 使用 __new__ 使用装饰器(decorator) 使用元类(metaclass) # mysingleton.py class ...

  9. 史上最全常用正则表达式(Javascript公众号推文)

    2017-04-13 zxin JavaScript很多不太懂正则的朋友,在遇到需要用正则校验数据时,往往是在网上去找很久,结果找来的还是不很符合要求.所以我最近把开发中常用的一些正则表达式整理了一下 ...

  10. 学习爬虫的day03 (通过代理去爬去数据)

    代理的IP通过去网上找# -*- coding: utf-8 -*- import re import _thread from time import sleep, ctime from urlli ...