python 装饰器
2016-06-29 21:15
691 查看
Python装饰器学习(九步门):http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html
Python装饰器学习:http://blog.csdn.net/thy38/article/details/4471421
Python装饰器与面向切面编程:http://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html
廖雪峰的官方网站
http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386819879946007bbf6ad052463ab18034f0254bf355000
Python 的闭包和装饰器:https://segmentfault.com/a/1190000004461404
装饰器就是对已有函数的进行的修饰,装饰器的功能是将被装饰的函数当作参数传递给与装饰器对应的函数(名称相同的函数),并返回包装后的被装饰的函数”
让我们回到刚开始的例子,在 deco 里面返回了一个 wrapper 函数对象。可以试着这么理解,deco的作用是给 func 进行装饰,wrapper 就是被装饰过的func。
怎么装饰 参数列表不一样 的多个函数?
从Python 2.7到Python 3.x就有不兼容的一些改动,比如2.x里的字符串用’xxx’表示str,Unicode字符串用u’xxx’表示unicode,而在3.x中,所有字符串都被视为unicode,因此,写u’xxx’和’xxx’是完全一致的,而在2.x中以’xxx’表示的str就必须写成b’xxx’,以此表示“二进制字符串”。
要直接把代码升级到3.x是比较冒进的,因为有大量的改动需要测试。相反,可以在2.7版本中先在一部分代码中测试一些3.x的特性,如果没有问题,再移植到3.x不迟。
Python提供了future模块,把下一个新版本的特性导入到当前版本,于是我们就可以在当前版本中测试一些新版本的特性。举例说明如下:
为了适应Python 3.x的新的字符串的表示方法,在2.7版本的代码中,可以通过unicode_literals来使用Python 3.x的新的# still running on Python 2.7
from future import unicode_literals
print ‘\’xxx\’ is unicode?’, isinstance(‘xxx’, unicode)
print ‘u\’xxx\’ is unicode?’, isinstance(u’xxx’, unicode)
print ‘\’xxx\’ is str?’, isinstance(‘xxx’, str)
print ‘b\’xxx\’ is str?’, isinstance(b’xxx’, str)上面的代码仍然在Python 2.7下运行,但结果显示去掉前缀u的’a string’仍是一个unicode,而加上前缀b的b’a string’才变成了str:
类似的情况还有除法运算。在Python 2.x中,对于除法有两种情况,如果是整数相除,结果仍是整数,余数会被扔掉,这种除法叫“地板除”:
10 / 3
3
要做精确除法,必须把其中一个数变成浮点数:
10.0 / 3
3.3333333333333335
而在Python 3.x中,所有的除法都是精确除法,地板除用//表示:
$ python3
Python 3.3.2 (default, Jan 22 2014, 09:54:40)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
Type “help”, “copyright”, “credits” or “license” for more information.
10 / 3
3.3333333333333335
10 // 3
3
如果你想在Python 2.7的代码中直接使用Python 3.x的除法,可以通过future模块的division实现:
from future import division
print ‘10 / 3 =’, 10 / 3
print ‘10.0 / 3 =’, 10.0 / 3
print ‘10 // 3 =’, 10 // 3
结果如下:
10 / 3 = 3.33333333333
10.0 / 3 = 3.33333333333
10 // 3 = 3
小结
由于Python是由社区推动的开源并且免费的开发语言,不受商业公司控制,因此,Python的改进往往比较激进,不兼容的情况时有发生。Python为了确保你能顺利过渡到新版本,特别提供了future模块,让你在旧的版本中试验新版本的一些特性。
所以,简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
注意到上面的新的int2函数,仅仅是把base参数重新设定默认值为2,但也可以在函数调用时传入其他值:
Python装饰器学习:http://blog.csdn.net/thy38/article/details/4471421
Python装饰器与面向切面编程:http://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html
廖雪峰的官方网站
http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386819879946007bbf6ad052463ab18034f0254bf355000
Python 的闭包和装饰器:https://segmentfault.com/a/1190000004461404
装饰器就是对已有函数的进行的修饰,装饰器的功能是将被装饰的函数当作参数传递给与装饰器对应的函数(名称相同的函数),并返回包装后的被装饰的函数”
def deco(func): print func return func @deco def foo():pass foo()
<function foo at 0x0000000003A35048>
def deco_functionNeedDoc(func): if func.__doc__==None: print func,':','has no __doc__,its a bad habit' else: print func,':',func.__doc__ return func @deco_functionNeedDoc def f(): print 'f() do someting' @deco_functionNeedDoc def g(): 'I have a __doc__' print 'g() do someting' f() g()
<function f at 0x0000000003A350B8> : has no __doc__,its a bad habit <function g at 0x00000000039ECF98> : I have a __doc__ f() do someting g() do someting
有参数装饰器
def decomaker(arg): '通常对arg会有一定的要求' def newDeco(func): print func,arg return func return newDeco @decomaker def foo():pass
'''示例2: 替换函数(装饰) 装饰函数的参数是被装饰的函数对象,返回原函数对象 装饰的实质语句: myfunc = deco(myfunc)''' def deco(func): print func,'my func' func() return func def foo(): print 'I am foo' return 'I am foo' foo_say=deco(foo)
<function foo at 0x0000000003A35208> my func I am foo <function __main__.foo>
'''示例3: 使用语法糖@来装饰函数,相当于“myfunc = deco(myfunc)” 但发现新函数只在第一次被调用,且原函数多调用了一次''' def deco(func): print func,func.__doc__ return func @deco def foo(): 'This is foo __doc__' print 'I am foo' return 'I am foo' for i in range(3): foo()
<function foo at 0x0000000003AF1F28> This is foo __doc__ I am foo I am foo I am foo
def deco(func): def _deco(a,b): print 'before' he=func(a,b) return he return _deco @deco def foo(a,b): print 'I am foo',a+b return a+b for i in range(3): foo(3,5)
before I am foo 8 before I am foo 8 before I am foo 8
让我们回到刚开始的例子,在 deco 里面返回了一个 wrapper 函数对象。可以试着这么理解,deco的作用是给 func 进行装饰,wrapper 就是被装饰过的func。
怎么装饰 参数列表不一样 的多个函数?
def deco(func): def wrapper(*args,**kwargs): func(*args,**kwargs) print "func is wraper" return wrapper @deco def foo(x): print 'In foo' print 'foo have %s' %x @deco def foo1(x,y): print 'In foo' print 'foo have %s:%s' %(x,y) if __name__=='__main__': foo('weiyudang') foo1('weiyudang','160') foo(range(10)) foo1(range(10),range(10,20))
In foo foo have weiyudang func is wraper In foo foo have weiyudang:160 func is wraper In foo foo have [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] func is wraper In foo foo have [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:[10, 11, 12, 13, 14, 15, 16, 17, 18, 19] func is wraper
#codeing:utf-8 class locker: def __init__(self): print "this is class" @staticmethod def acquire(): print 'locker.acquire() called' def deco(cls): def wrapper(func): def __wrapper(): cls.acquire() try: return func finally: print 'final' return __wrapper return wrapper @deco(locker) def myfunc(): print 'This is not foo' myfunc()
final This is not foo
#codeing:utf-8 import time import random def jishi(func): def deco(*args,**kwargs): 'This is deco' start=time.clock() func() end=time.clock() print 'use time:%f s'%(end-start) return deco def shuoming(func): def deco1(*args,**kwargs): print func.__doc__ func() return deco1 ## 注意装饰器的顺序 @shuoming @jishi def myfoo(): 'This is test' sum(range(100002)) myfoo() print myfoo.__name__ ### 经过装饰之后函数的__name__属性发生变化,需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错 ##Python内置的functools.wraps就是干这个事的,所以,一个完整的decorator的写法如下:
This is deco use time:0.006677 s deco1
import functools def log(text): print 0 def decorator(func): print 1 @functools.wraps(func) def wrapper(*args, **kw): print '%s %s():' % (text, func.__name__) return func(*args, **kw) print 2 return wrapper print 3 return decorator @log(u'执行') def foo(x): print x sum(range(100)) print range(3) foo('wwee') print foo.__name__
0 3 1 2 执行 foo(): wwee [0, 1, 2] foo
使用__future__
Python的每个新版本都会增加一些新的功能,或者对原来的功能作一些改动。有些改动是不兼容旧版本的,也就是在当前版本运行正常的代码,到下一个版本运行就可能不正常了。从Python 2.7到Python 3.x就有不兼容的一些改动,比如2.x里的字符串用’xxx’表示str,Unicode字符串用u’xxx’表示unicode,而在3.x中,所有字符串都被视为unicode,因此,写u’xxx’和’xxx’是完全一致的,而在2.x中以’xxx’表示的str就必须写成b’xxx’,以此表示“二进制字符串”。
要直接把代码升级到3.x是比较冒进的,因为有大量的改动需要测试。相反,可以在2.7版本中先在一部分代码中测试一些3.x的特性,如果没有问题,再移植到3.x不迟。
Python提供了future模块,把下一个新版本的特性导入到当前版本,于是我们就可以在当前版本中测试一些新版本的特性。举例说明如下:
为了适应Python 3.x的新的字符串的表示方法,在2.7版本的代码中,可以通过unicode_literals来使用Python 3.x的新的# still running on Python 2.7
from future import unicode_literals
print ‘\’xxx\’ is unicode?’, isinstance(‘xxx’, unicode)
print ‘u\’xxx\’ is unicode?’, isinstance(u’xxx’, unicode)
print ‘\’xxx\’ is str?’, isinstance(‘xxx’, str)
print ‘b\’xxx\’ is str?’, isinstance(b’xxx’, str)上面的代码仍然在Python 2.7下运行,但结果显示去掉前缀u的’a string’仍是一个unicode,而加上前缀b的b’a string’才变成了str:
$ python task.py 'xxx' is unicode? True u'xxx' is unicode? True 'xxx' is str? False b'xxx' is str? True
类似的情况还有除法运算。在Python 2.x中,对于除法有两种情况,如果是整数相除,结果仍是整数,余数会被扔掉,这种除法叫“地板除”:
10 / 3
3
要做精确除法,必须把其中一个数变成浮点数:
10.0 / 3
3.3333333333333335
而在Python 3.x中,所有的除法都是精确除法,地板除用//表示:
$ python3
Python 3.3.2 (default, Jan 22 2014, 09:54:40)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
Type “help”, “copyright”, “credits” or “license” for more information.
10 / 3
3.3333333333333335
10 // 3
3
如果你想在Python 2.7的代码中直接使用Python 3.x的除法,可以通过future模块的division实现:
from future import division
print ‘10 / 3 =’, 10 / 3
print ‘10.0 / 3 =’, 10.0 / 3
print ‘10 // 3 =’, 10 // 3
结果如下:
10 / 3 = 3.33333333333
10.0 / 3 = 3.33333333333
10 // 3 = 3
小结
由于Python是由社区推动的开源并且免费的开发语言,不受商业公司控制,因此,Python的改进往往比较激进,不兼容的情况时有发生。Python为了确保你能顺利过渡到新版本,特别提供了future模块,让你在旧的版本中试验新版本的一些特性。
偏函数
functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2import functools #进制转换base int('22',base=2) int2=functools.partial(int,base=2) int2('1001') 9
所以,简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
注意到上面的新的int2函数,仅仅是把base参数重新设定默认值为2,但也可以在函数调用时传入其他值:
相关文章推荐
- python笔记——列表中的函数
- 初识 Python 1
- python crypto
- day04_python random模块随机生成验证码
- Python疑问系列
- 树莓派GPIO控制--python篇
- Python3之paramiko模块
- Python3之shutil模块
- Python3之random模块
- python django1.9.7 ubuntu 14.03 环境部署记录
- Python ctype sizeof incorrect!
- Python 函数和模块
- Python操作RabbitMQ服务器实现消息队列的路由功能
- python自动发送报警监控邮件
- Python(Django) Restful Vue developent flow chart
- spark机器学习笔记:(四)用Spark Python构建分类模型(上)
- 编译Python源代码
- Python通过RabbitMQ服务器实现交换机功能的实例教程
- zabbix 微信报警( python 2.x )
- python复制目录