python 学习分享-装饰器篇
本篇内容为偷窃的~哈哈,借用一下,我就是放在自己这里好看。
引用地址:http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html
第一步:最简单的函数,准备附加额外功能
'''示例1: 最简单的函数,表示调用了两次''' def myfunc():
print("myfunc() called.") myfunc()
myfunc()
第二步:使用装饰函数在函数执行前和执行后分别附加额外功能
def deco(func):
print("before myfunc() called.")
func()
print(" after myfunc() called.")
return func def myfunc():
print(" myfunc() called.") myfunc = deco(myfunc) myfunc()
myfunc()
第三步:使用语法糖@来装饰函数
'''示例3: 使用语法糖@来装饰函数,相当于“myfunc = deco(myfunc)”
但发现新函数只在第一次被调用,且原函数多调用了一次''' def deco(func):
print("before myfunc() called.")
func()
print(" after myfunc() called.")
return func @deco
def myfunc():
print(" myfunc() called.") myfunc()
myfunc()
第四步:使用内嵌包装函数来确保每次新函数都被调用
'''示例4: 使用内嵌包装函数来确保每次新函数都被调用,
内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象''' def deco(func):
def _deco():
print("before myfunc() called.")
func()
print(" after myfunc() called.")
# 不需要返回func,实际上应返回原函数的返回值
return _deco @deco
def myfunc():
print(" myfunc() called.")
return 'ok' myfunc()
myfunc()
第五步:对带参数的函数进行装饰
'''示例5: 对带参数的函数进行装饰,
内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象''' def deco(func):
def _deco(a, b):
print("before myfunc() called.")
ret = func(a, b)
print(" after myfunc() called. result: %s" % ret)
return ret
return _deco @deco
def myfunc(a, b):
print(" myfunc(%s,%s) called." % (a, b))
return a + b myfunc(1, 2)
myfunc(3, 4)
第六步:对参数数量不确定的函数进行装饰
'''示例6: 对参数数量不确定的函数进行装饰,
参数用(*args, **kwargs),自动适应变参和命名参数''' def deco(func):
def _deco(*args, **kwargs):
print("before %s called." % func.__name__)
ret = func(*args, **kwargs)
print(" after %s called. result: %s" % (func.__name__, ret))
return ret
return _deco @deco
def myfunc(a, b):
print(" myfunc(%s,%s) called." % (a, b))
return a+b @deco
def myfunc2(a, b, c):
print(" myfunc2(%s,%s,%s) called." % (a, b, c))
return a+b+c myfunc(1, 2)
myfunc(3, 4)
myfunc2(1, 2, 3)
myfunc2(3, 4, 5)
第七步:让装饰器带参数
'''示例7: 在示例4的基础上,让装饰器带参数,
和上一示例相比在外层多了一层包装。
装饰函数名实际上应更有意义些''' def deco(arg):
def _deco(func):
def __deco():
print("before %s called [%s]." % (func.__name__, arg))
func()
print(" after %s called [%s]." % (func.__name__, arg))
return __deco
return _deco @deco("mymodule")
def myfunc():
print(" myfunc() called.") @deco("module2")
def myfunc2():
print(" myfunc2() called.") myfunc()
myfunc2()
第八步:让装饰器带 类 参数
'''示例8: 装饰器带类参数''' class locker:
def __init__(self):
print("locker.__init__() should be not called.") @staticmethod
def acquire():
print("locker.acquire() called.(这是静态方法)") @staticmethod
def release():
print(" locker.release() called.(不需要对象实例)") def deco(cls):
'''cls 必须实现acquire和release静态方法'''
def _deco(func):
def __deco():
print("before %s called [%s]." % (func.__name__, cls))
cls.acquire()
try:
return func()
finally:
cls.release()
return __deco
return _deco @deco(locker)
def myfunc():
print(" myfunc() called.") myfunc()
myfunc()
第九步:装饰器带类参数,并分拆公共类到其他py文件中,同时演示了对一个函数应用多个装饰器
'''mylocker.py: 公共类 for 示例9.py''' class mylocker:
def __init__(self):
print("mylocker.__init__() called.") @staticmethod
def acquire():
print("mylocker.acquire() called.") @staticmethod
def unlock():
print(" mylocker.unlock() called.") class lockerex(mylocker):
@staticmethod
def acquire():
print("lockerex.acquire() called.") @staticmethod
def unlock():
print(" lockerex.unlock() called.") def lockhelper(cls):
'''cls 必须实现acquire和release静态方法'''
def _deco(func):
def __deco(*args, **kwargs):
print("before %s called." % func.__name__)
cls.acquire()
try:
return func(*args, **kwargs)
finally:
cls.unlock()
return __deco
return _deco
'''示例9: 装饰器带类参数,并分拆公共类到其他py文件中
同时演示了对一个函数应用多个装饰器''' from mylocker import * class example:
@lockhelper(mylocker)
def myfunc(self):
print(" myfunc() called.") @lockhelper(mylocker)
@lockhelper(lockerex)
def myfunc2(self, a, b):
print(" myfunc2() called.")
return a + b if __name__=="__main__":
a = example()
a.myfunc()
print(a.myfunc())
print(a.myfunc2(1, 2))
print(a.myfunc2(3, 4))
下面是参考资料,当初有不少地方没看明白,真正练习后才明白些:
1. Python装饰器学习 http://blog.csdn.net/thy38/article/details/4471421
2. Python装饰器与面向切面编程 http://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html
3. Python装饰器的理解 http://apps.hi.baidu.com/share/detail/17572338
这是在Python学习小组上介绍的内容,现学现卖、多练习是好的学习方式。
第一步:最简单的函数,准备附加额外功能
1
2
3
4
5
6
7
8
|
# -*- coding:gbk -*- '''示例1: 最简单的函数,表示调用了两次''' def myfunc(): print ( "myfunc() called." ) myfunc() myfunc() |
第二步:使用装饰函数在函数执行前和执行后分别附加额外功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# -*- coding:gbk -*- '''示例2: 替换函数(装饰) 装饰函数的参数是被装饰的函数对象,返回原函数对象 装饰的实质语句: myfunc = deco(myfunc)''' def deco(func): print ( "before myfunc() called." ) func() print ( " after myfunc() called." ) return func def myfunc(): print ( " myfunc() called." ) myfunc = deco(myfunc) myfunc() myfunc() |
第三步:使用语法糖@来装饰函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# -*- coding:gbk -*- '''示例3: 使用语法糖@来装饰函数,相当于“myfunc = deco(myfunc)” 但发现新函数只在第一次被调用,且原函数多调用了一次''' def deco(func): print ( "before myfunc() called." ) func() print ( " after myfunc() called." ) return func @deco def myfunc(): print ( " myfunc() called." ) myfunc() myfunc() |
第四步:使用内嵌包装函数来确保每次新函数都被调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
# -*- coding:gbk -*- '''示例4: 使用内嵌包装函数来确保每次新函数都被调用, 内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象''' def deco(func): def _deco(): print ( "before myfunc() called." ) func() print ( " after myfunc() called." ) # 不需要返回func,实际上应返回原函数的返回值 return _deco @deco def myfunc(): print ( " myfunc() called." ) return 'ok' myfunc() myfunc() |
第五步:对带参数的函数进行装饰
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
# -*- coding:gbk -*- '''示例5: 对带参数的函数进行装饰, 内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象''' def deco(func): def _deco(a, b): print ( "before myfunc() called." ) ret = func(a, b) print ( " after myfunc() called. result: %s" % ret) return ret return _deco @deco def myfunc(a, b): print ( " myfunc(%s,%s) called." % (a, b)) return a + b myfunc( 1 , 2 ) myfunc( 3 , 4 ) |
第六步:对参数数量不确定的函数进行装饰
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
# -*- coding:gbk -*- '''示例6: 对参数数量不确定的函数进行装饰, 参数用(*args, **kwargs),自动适应变参和命名参数''' def deco(func): def _deco( * args, * * kwargs): print ( "before %s called." % func.__name__) ret = func( * args, * * kwargs) print ( " after %s called. result: %s" % (func.__name__, ret)) return ret return _deco @deco def myfunc(a, b): print ( " myfunc(%s,%s) called." % (a, b)) return a + b @deco def myfunc2(a, b, c): print ( " myfunc2(%s,%s,%s) called." % (a, b, c)) return a + b + c myfunc( 1 , 2 ) myfunc( 3 , 4 ) myfunc2( 1 , 2 , 3 ) myfunc2( 3 , 4 , 5 ) |
第七步:让装饰器带参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# -*- coding:gbk -*- '''示例7: 在示例4的基础上,让装饰器带参数, 和上一示例相比在外层多了一层包装。 装饰函数名实际上应更有意义些''' def deco(arg): def _deco(func): def __deco(): print ( "before %s called [%s]." % (func.__name__, arg)) func() print ( " after %s called [%s]." % (func.__name__, arg)) return __deco return _deco @deco ( "mymodule" ) def myfunc(): print ( " myfunc() called." ) @deco ( "module2" ) def myfunc2(): print ( " myfunc2() called." ) myfunc() myfunc2() |
第八步:让装饰器带 类 参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
# -*- coding:gbk -*- '''示例8: 装饰器带类参数''' class locker: def __init__( self ): print ( "locker.__init__() should be not called." ) @staticmethod def acquire(): print ( "locker.acquire() called.(这是静态方法)" ) @staticmethod def release(): print ( " locker.release() called.(不需要对象实例)" ) def deco( cls ): '''cls 必须实现acquire和release静态方法''' def _deco(func): def __deco(): print ( "before %s called [%s]." % (func.__name__, cls )) cls .acquire() try : return func() finally : cls .release() return __deco return _deco @deco (locker) def myfunc(): print ( " myfunc() called." ) myfunc() myfunc() |
第九步:装饰器带类参数,并分拆公共类到其他py文件中,同时演示了对一个函数应用多个装饰器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
# -*- coding:gbk -*- '''mylocker.py: 公共类 for 示例9.py''' class mylocker: def __init__( self ): print ( "mylocker.__init__() called." ) @staticmethod def acquire(): print ( "mylocker.acquire() called." ) @staticmethod def unlock(): print ( " mylocker.unlock() called." ) class lockerex(mylocker): @staticmethod def acquire(): print ( "lockerex.acquire() called." ) @staticmethod def unlock(): print ( " lockerex.unlock() called." ) def lockhelper( cls ): '''cls 必须实现acquire和release静态方法''' def _deco(func): def __deco( * args, * * kwargs): print ( "before %s called." % func.__name__) cls .acquire() try : return func( * args, * * kwargs) finally : cls .unlock() return __deco return _deco |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
# -*- coding:gbk -*- '''示例9: 装饰器带类参数,并分拆公共类到其他py文件中 同时演示了对一个函数应用多个装饰器''' from mylocker import * class example: @lockhelper (mylocker) def myfunc( self ): print ( " myfunc() called." ) @lockhelper (mylocker) @lockhelper (lockerex) def myfunc2( self , a, b): print ( " myfunc2() called." ) return a + b if __name__ = = "__main__" : a = example() a.myfunc() print (a.myfunc()) print (a.myfunc2( 1 , 2 )) print (a.myfunc2( 3 , 4 )) |
下面是参考资料,当初有不少地方没看明白,真正练习后才明白些:
1. Python装饰器学习 http://blog.csdn.net/thy38/article/details/4471421
2. Python装饰器与面向切面编程 http://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html
3. Python装饰器的理解 http://apps.hi.baidu.com/share/detail/17572338
python 学习分享-装饰器篇的更多相关文章
- python学习笔记--装饰器
1.首先是一个很无聊的函数,实现了两个数的加法运算: def f(x,y): print x+y f(2,3) 输出结果也ok 5 2.可是这时候我们感觉输出结果太单一了点,想让代码的输出多一点看起来 ...
- python学习之装饰器-
python的装饰器 2018-02-26 在了解python的装饰器之前我们得了解python的高阶函数 python的高阶函数我们能返回一个函数名并且能将函数名作为参数传递 def outer() ...
- python学习day14 装饰器(二)&模块
装饰器(二)&模块 #普通装饰器基本格式 def wrapper(func): def inner(): pass return func() return inner def func(): ...
- Python学习 :装饰器
装饰器(函数) 装饰器作为一个函数,可以为其他函数在不修改原函数代码的前提下添加新的功能 装饰器的返回值是一个函数对象.它经常用于有切面需求的场景,比如:插入日志.性能测试.事务处理.缓存.权限校验等 ...
- python学习之-- 装饰器
高阶函数+嵌套函数 == 装饰器 什么是装饰器: 其实也是一个函数. 功能:为其他的函数添加附加功能 原则:不能修改被装饰的函数的源代码和调用方式 学习装饰器前首先要明白以下3条事项: 1:函数 即 ...
- Python学习笔记--装饰器的实验
装饰器既然可以增加原来函数的功能,那能不能改变传给原函数的参数呢? 我们实验一下,先上代码: #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date ...
- 6月4日 python学习总结 装饰器复习
1. 装饰器的原理以及为什么要使用装饰器 在代码运行期间动态增加功能的方式,称之为"装饰器"(Decorator). 在不影响原代码结构的情况下为其添加功能 2. 装饰器的基本 ...
- python学习 day13 装饰器(一)&推导式
装饰器&推导式 传参位置参数在前,关键词参数在后 函数不被调用内部代码不被执行 函数在被调用的时候,每次都会开辟一个新的内存地址,互不干扰 #经典案例 def func(num): def i ...
- Python学习之装饰器进阶
函数知识回顾: 函数的参数分为:实参和形参. 实参:调用函数的时候传入的参数: 形参:分为3种(位置参数.默认参数.动态传参) 位置参数:必须传值 def aaa(a,b): print(a,b) a ...
随机推荐
- datagrid数据表格使用总结
一.加载的css文件 easyui 基本样式: <link href="../easyui/easyui1.5.css" rel="stylesheet" ...
- python 之开发工具 sublimetext 3
一.前言 由于个人工作内容太过于繁杂,记忆力又不好,为日后使用的方便,故简单的记录了本篇关于sublimetext 3的初始化安装和部分插件内容的记录.目前最新的版本也是3.0以上版本了,故我这里使用 ...
- Js面向对象之观察者模式
//模拟一个目标可能拥有的一些列依赖 function ObserverList() { this.observerList = []; }; //添加一个观察者 ObserverList.proto ...
- mustache.js 数组循环的索引
在使用mustache作为模板引擎时,想要利用数组中的对象的索引排序,却发现mustache中无法获得数组索引,在一番搜索之后,发现在数组的对象中加入索引,就可以了,示例如下 /html {{#dat ...
- POJ 3421 X-factor Chains(构造)
这条链依次乘一个因子.因为n<2^20,sqrt(n)分解因子,相同的因子相对顺序取一个. 组合公式计算一下就好. #include<cstdio> #include<iost ...
- POJ 1065 Wooden Sticks(LIS,最少链划分)
题意:求二维偏序的最少链划分. 用到Dilworth定理:最少链划分=最长反链.(对偶也成立,个人认为区别只是一个维度上的两个方向,写了个简单的证明 相关概念:偏序集,链,反链等等概念可以参考这里:h ...
- 【BZOJ4033】[HAOI2015] 树上染色(树形DP)
点此看题面 大致题意: 给你一棵点数为N的带权树,要你在这棵树中选择K个点染成黑色,并将其他的N-K个点染成白色.要求你求出黑点两两之间的距离加上白点两两之间距离的和的最大值. 树形\(DP\) 这道 ...
- 【HDU4507】恨7不成妻(数位DP)
点此看题面 大致题意: 让你求出一段区间内与\(7\)无关的数的平方和.与\(7\)无关的数指整数中任意一位不为\(7\).整数的每一位加起来的和不是\(7\)的整数倍.这个整数不是\(7\)的倍数. ...
- Abode Dreamweaver cc 安装与激活
原文链接Abode Dreamweaver CC是Adobe宣布放弃Creative Suite系列产品后推出的新版Creative Cloud产品,功能上修复了CS6中出现的选取代码不精准的问题,最 ...
- java设计模式——单例模式(三)
容器单例模式 之前学习Structs2,Spring框架时,经常会听到单例,多例.虽然这与单例模式不太一样,但是都很类似.在程序运行的时候,就加载所有的实例,然后用的时候直接取出 看下面代码: /** ...