<style>
<!--
h1, h2, h3, h4, h5, h6, p, blockquote
{margin:0;
padding:0}
body
{font-family:"Helvetica Neue",Helvetica,"Hiragino Sans GB",Arial,sans-serif;
font-size:13px;
line-height:18px;
color:#737373;
background-color:white;
margin:10px 13px 10px 13px}
table
{margin:10px 0 15px 0;
border-collapse:collapse}
td, th
{border:1px solid #ddd;
padding:3px 10px}
th
{padding:5px 10px}
a
{color:#0069d6}
a:hover
{color:#0050a3;
text-decoration:none}
a img
{border:none}
p
{margin-bottom:9px}
h1, h2, h3, h4, h5, h6
{color:#404040;
line-height:36px}
h1
{margin-bottom:18px;
font-size:30px}
h2
{font-size:24px}
h3
{font-size:18px}
h4
{font-size:16px}
h5
{font-size:14px}
h6
{font-size:13px}
hr
{margin:0 0 19px;
border:0;
border-bottom:1px solid #ccc}
blockquote
{padding:13px 13px 21px 15px;
margin-bottom:18px;
font-family:georgia,serif;
font-style:italic}
blockquote:before
{content:"\201C";
font-size:40px;
margin-left:-10px;
font-family:georgia,serif;
color:#eee}
blockquote p
{font-size:14px;
font-weight:300;
line-height:18px;
margin-bottom:0;
font-style:italic}
code, pre
{font-family:Monaco,Andale Mono,Courier New,monospace}
pre
{display:block;
padding:14px;
margin:0 0 18px;
line-height:16px;
font-size:11px;
border:1px solid #d9d9d9;
white-space:pre-wrap;
word-wrap:break-word}
pre code
{background-color:#fff;
color:#737373;
font-size:11px;
padding:0}
-->
</style>
博客迁往:新地址(点击直达)
新博客使用markdown维护,线下有版本库,自己写的所以会定时更新同步,同时提供更好的导航和阅读体验
csdn对markdown支持不好,所以旧版不会花时间进行同步修订,抱歉
-----------------------------------------------
想找个地方快乐的coding,貌似不是一件容易的事情。
一时冲动,不过后路已断,做自己想做的事情,总要付出一些代价的,坚持吧,只能。
吐槽下,本周各种事情,搞得如越级打怪般艰难。周六,去三小时,回来三小时,大败而归,但是还是学到不少东西。
差距还是有的,虽然自信可以在最短时间补上,但是,需要成本。
总之,貌似时机不对,哎以上废话,进入正题
上周六碰到了,一周忙碌,今天稍微理下,待补全,资料主要来源于书籍,网络&self.coding()。有任何问题,请指正哈
基本概念
具体概念自己google
装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理, Web权限校验, Cache等。
很有名的例子,就是咖啡,加糖的咖啡,加牛奶的咖啡。本质上,还是咖啡,只是在原有的东西上,做了“装饰”,使之附加一些功能或特性。
例如记录日志,需要对某些函数进行记录
笨的办法,每个函数加入代码,如果代码变了,就悲催了
装饰器的办法,定义一个专门日志记录的装饰器,对需要的函数进行装饰,搞定
优点
抽离出大量函数中与函数功能本身无关的雷同代码并继续重用
即,可以将函数“修饰”为完全不同的行为,可以有效的将业务逻辑正交分解,如用于将权限和身份验证从业务中独立出来
概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能
Python中的装饰器
在Python中,装饰器实现是十分方便的
原因是:函数可以被扔来扔去。
函数作为一个对象:
A.可以被赋值给其他变量,可以作为返回值
B.可以被定义在另外一个函数内
def:
装饰器是一个函数,一个用来包装函数的函数,装饰器在函数申明完成的时候被调用,调用之后返回一个修改之后的函数对象,将其重新赋值原来的标识符,并永久丧失对原始函数对象的访问(申明的函数被换成一个被装饰器装饰过后的函数)
当我们对某个方法应用了装饰方法后, 其实就改变了被装饰函数名称所引用的函数代码块入口点,使其重新指向了由装饰方法所返回的函数入口点。
由此我们可以用decorator改变某个原有函数的功能,添加各种操作,或者完全改变原有实现
分类:
装饰器分为无参数decorator,有参数decorator
* 无参数decorator
生成一个新的装饰器函数
* 有参decorator
有参装饰,装饰函数先处理参数,再生成一个新的装饰器函数,然后对函数进行装饰
装饰器有参/无参,函数有参/无参,组合共4种
具体定义:
decorator方法
A.把要装饰的方法作为输入参数,
B.在函数体内可以进行任意的操作(可以想象其中蕴含的威力强大,会有很多应用场景),
C.只要确保最后返回一个可执行的函数即可(可以是原来的输入参数函数, 或者是一个新函数)
无参数装饰器 – 包装无参数函数
不需要针对参数进行处理和优化
def decorator(func):
print "hello"
return func
@decorator
def foo():
pass
foo()
foo()等价于:
foo = decorator(foo)
foo()
无参数装饰器 – 包装带参数函数
def decorator_func_args(func):
def handle_args(*args, **kwargs): #处理传入函数的参数
print "begin"
func(*args, **kwargs) #函数调用
print "end"
return handle_args
@decorator_func_args
def foo2(a, b=2):
print a, b
foo2(1)
foo2(1)等价于
foo2 = decorator_func_args(foo2)
foo2(1)
带参数装饰器 – 包装无参数函数
def decorator_with_params(arg_of_decorator):#这里是装饰器的参数
print arg_of_decorator
#最终被返回的函数
def newDecorator(func):
print func
return func
return newDecorator
@decorator_with_params("deco_args")
def foo3():
pass
foo3()
与前面的不同在于:比上一层多了一层封装,先传递参数,再传递函数名
第一个函数decomaker是装饰函数,它的参数是用来加强“加强装饰”的。由于此函数并非被装饰的函数对象,所以在内部必须至少创建一个接受被装饰函数的函数,然后返回这个对象(实际上此时foo3= decorator_with_params(arg_of_decorator)(foo3))
带参数装饰器– 包装带参数函数
def decorator_whith_params_and_func_args(arg_of_decorator):
def handle_func(func):
def handle_args(*args, **kwargs):
print "begin"
func(*args, **kwargs)
print "end"
print arg_of_decorator, func, args,kwargs
return handle_args
return handle_func
@decorator_whith_params_and_func_args("123")
def foo4(a, b=2):
print "Content"
foo4(1, b=3)
内置装饰器
内置的装饰器有三个:staticmethod,classmethod, property
class A():
@staticmethod
def test_static():
print "static"
def test_normal(self):
print "normal"
@classmethod
def test_class(cls):
print "class", cls
a = A()
A.test_static()
a.test_static()
a.test_normal()
a.test_class()
结果:
static
static
normal
class __main__.A
A.test_static
staticmethod 类中定义的实例方法变成静态方法
基本上和一个全局函数差不多(不需要传入self,只有一般的参数),只不过可以通过类或类的实例对象来调用,不会隐式地传入任何参数。
类似于静态语言中的静态方法
B.test_normal
普通对象方法:普通对象方法至少需要一个self参数,代表类对象实例
C.test_class
类中定义的实例方法变成类方法
classmethod需要传入类对象,可以通过实例和类对象进行调用。
是和一个class相关的方法,可以通过类或类实例调用,并将该class对象(不是class的实例对象)隐式地当作第一个参数传入。
就这种方法可能会 比较奇怪一点,不过只要你搞清楚了python里class也是个真实地存在于内存中的对象,而不是静态语言中只存在于编译期间的类型,就好办了。正常的方法就是和一个类的实例对象相关的方法,通过类实例对象进行调用,并将该实例对象隐式地作为第一个参数传入,这个也和其它语言比较像。
D.区别
staticmethod,classmethod相当于全局方法,一般用在抽象类或父类中。一般与具体的类无关。
类方法需要额外的类变量cls,当有子类继承时,调用类方法传入的类变量cls是子类,而不是父类。
类方法和静态方法都可以通过类对象和类的实例对象访问
定义方式,传入的参数,调用方式都不相同。
E.property
对类属性的操作,类似于java中定义getter/setter
class B():
def __init__(self):
self.__prop = 1
@property
def prop(self):
print "call get"
return self.__prop
@prop.setter
def prop(self, value):
print "call set"
self.__prop = value
@prop.deleter
def prop(self):
print "call del"
del self.__prop
其他
A.装饰器的顺序很重要,需要注意
@A
@B
@C
def f ():
等价于
f = A(B(C(f)))
B.decorator的作用对象可以是模块级的方法或者类方法
C.functools模块提供了两个装饰器。这个模块是Python 2.5后新增的。
functools.wraps(func)total_ordering(cls)这个具体自己去看吧,后续用到了再补充
一个简单例子
通过一个变量,控制调用函数时是否统计时间
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#@author: wklken@yeah.net
#@version: a test of decorator
#@date: 20121027
#@desc: just a test
import logging
from time import time
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
is_debug = True
def count_time(is_debug):
def handle_func(func):
def handle_args(*args, **kwargs):
if is_debug:
begin = time()
func(*args, **kwargs)
logging.debug( "[" + func.__name__ + "] -> " + str(time() - begin) )
else:
func(*args, **kwargs)
return handle_args
return handle_func
def pr():
for i in range(1,1000000):
i = i * 2
print "hello world"
def test():
pr()
@count_time(is_debug)
def test2():
pr()
@count_time(False)
def test3():
pr()
if __name__ == "__main__":
test()
test2()
test3()
结果:
hello world
hello world
DEBUG:root:[test2] -> 0.0748538970947
hello world
The end!
wklken
Gighub: https://github.com/wklken
Blog: http://wklken.sinaapp.com/
2012-10-27
转载请注明出处,谢谢!
分享到:
相关推荐
官方离线安装包,亲测可用
超时装饰器安装从源代码: python setup.py install从pypi: pip install timeout-decorator用法import timeimport timeout_decorator@timeout_decorator.timeout(5)def mytest(): print("Start") for i in range(1,...
vue脚手架 本框架已开发了所属相关组件,如有 定制组件 需求可联系
Nuxt属性装饰器 方便的ES / TypeScript装饰器,用于Nuxt中的类样式Vue组件(基于)以及(基于 )和Vuex(基于) 该库完全依赖于 。 执照 麻省理工学院执照 安装 安装非常容易 npm i -S nuxt-property-decorator ...
使用装饰器自动生成swagger json文档 安装 npm install koa-swagger-decorator 贡献指南 请参考创建PR或发行前。 介绍 Koa Swagger装饰器 使用装饰器自动生成swagger json文档,添加对swagger定义的支持验证 基于 ...
离线安装包,亲测可用
python-decorator-3.0.1-3.1.el6.noarch
它比React组件的core-decorator绑定装饰器更轻巧,更快。安装npm install react - bind - decorator -- save用法: import reactbind from 'react-bind-decorator' ;@ reactbind ( )class Foo extends React . ...
“就增加功能来说,Decorator 模式相比生成子类更为灵活” 这句话的含义是,组合比继承更灵活,当可拓展的功能很多时,继承方案会产生大量的子类,而组合可以提
官方离线安装包,亲测可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,亲测可用。使用rpm -ivh [rpm完整包名] 进行安装
Vue装饰器注入ES6装饰器对Vue.js的依赖注入安装如果您使用的是Webpack或类似产品: npm i --save-dev vue-decorator-inject 否则,-- --save可能更明智。介绍该库将容器与类似于Symfony中的容器的接口结合在一起,并...
eslint插件使用装饰器 这是eslint的自定义插件,可在方法上强制使用装饰器。 注意 这仅适用于@typescript-eslint插件 安装 npm install --save-dev eslint-plugin-use-decorator 用法 将此添加到您的.eslintrc // ...
前端开源库-pure-render-decorator纯渲染装饰,使反应组件纯。
@ redtea / craco-parameter-decorator 这个插件将为您的项目设置 。 支持: create-react-app:3.x,4.x craco:5.x,6.x :hammer_and_wrench: 安装 纱 $ yarn add -E @redtea/craco-parameter-decorator NPM...
eslint-plugin-decorator-position 一个ESlint插件,它提供一组规则以强制一致的装饰器位置 :red_exclamation_mark: 要求 >= 5 >= 8.5 :rocket: 用法1.安装插件yarn add --dev eslint-plugin-decorator-position ...
koa-decorator-ts Koa装饰器(带有TypeScript) 安装 npm i koa-decorator-ts --save /* or */ yarn add koa-decorator-ts 介绍 此包装是用于koa的装饰器,包括koa-router graohql。 您可以使用装饰器定义路由路径...
python_base.py: 千行代码入门Python python_visual.py: 15张图入门Matplotlib python_visual_animation.py: 使用Matplotlib画...python_decorator.py: Python进阶: 通过实例详解装饰器(附代码) python_datetime.p
Laravel开发-cache-decorator Laravel5的魔法(就像节省很多手工工作一样)缓存装饰器。设计用于存储库,但很容易用于其他用途。如果有足够的兴趣,可以使框架不可知论。
Vue属性装饰器该库完全依赖于vue-class-component,因此在使用该库之前,请阅读其自述文件。 许可MIT许可Ins Vue属性装饰器该库完全取决于vue-class-component,因此在使用该库之前,请阅读其自述文件。 许可证MIT...