Python装饰器学习(九步入门)

 

这是在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 装饰器学习的更多相关文章

  1. (转载)Python装饰器学习

    转载出处:http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html 这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方 ...

  2. Python装饰器学习

    Python装饰器学习(九步入门)   这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 ? 1 2 3 4 5 6 7 8 # -*- ...

  3. Python 装饰器学习心得

    最近打算重新开始记录自己的学习过程,于是就捡起被自己废弃了一年多的博客.这篇学习笔记主要是记录近来看的有关Python装饰器的东西. 0. 什么是装饰器? 本质上来说,装饰器其实就是一个特殊功能的函数 ...

  4. python 装饰器学习(decorator)

    最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initi ...

  5. Python装饰器学习(九步入门)

    这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 ? 1 2 3 4 5 6 7 8 # -*- coding:gbk -*- '''示 ...

  6. python装饰器学习详解-函数部分

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 最近阅读<流畅的python>看见其用函数写装饰器部分写的很好,想写一些自己的读书笔记. ...

  7. Python 装饰器学习以及实际使用场景实践

    前言 前几天在看Flask框架,对于非常神奇的@语法,不是非常的理解,回来补装饰器的功课.阅读很多的关于装饰器的文章,自己整理一下,适合自己的思路的方法和例子,与大家分享. app = Flask(_ ...

  8. python装饰器学习笔记

    定义:本质上就是个函数,(装饰器其他函数)就是为了给其他函数添加附加功能 原则:1.不能修改被装饰的函数的源代码 2.不能修改被装饰的函数的调用方式 #-*-coding:utf-8-*- 1 imp ...

  9. 【转】九步学习python装饰器

    本篇日志来自:http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html 纯转,只字未改.只是为了学习一下装饰器.其实现在也是没有太看明白 ...

随机推荐

  1. flume 不报错但是不能正常使用

    flume-ng agent --conf ./conf/ --conf-file ./conf/test1.conf --name a1 -Dflume.root.logger=INFO,conso ...

  2. java多线程基础

    多线程基础 读书练习照猫画虎 package Threadtest; import java.util.Date; import java.util.concurrent.ArrayBlockingQ ...

  3. 如何在IDEA 中使用Git

    1,下载最新的 git 包 地址: https://git-scm.com/download/win 下载便携版 64,32 根据个人爱好   2,解压后随便放个位置即可,例如图: (不太建议使用它自 ...

  4. Imagenet tools install on windows

    1.find the pyrcc4.exe path: C:\Anaconda2\Library\bin 2.cmd: pyrcc4 -o resources.py resources.qrc 3.a ...

  5. 如何判断exe或dll的目标平台及是否是.NET?

    1. COFF文件头中偏移0处的Machine指示目标机器类型(IMAGE_FILE_MACHINE_AMD64等),偏移18处的Characteristics位指示文件属性(IMAGE_FILE_3 ...

  6. [Linux] - 攻击查看与IP查封

    查看80端口的连接数 netstat -nat|grep -i "|wc -l 查看Nginx的日志命令 tail -f access.log 统计IP访问数 awk '{aaa[$1]++ ...

  7. AES--高级数据加密标准

    AES--高级数据加密标准 对称密码体制的发展趋势将以分组密码为重点.分组密码算法通常由密钥扩展算法和加密(解密)算法两部分组成.密钥扩展算法将b字节用户主密钥扩展成r个子密钥.加密算法由一个密码学上 ...

  8. core文件

    1.ulimit  -c查看是否可以产生core文件 打印0表示当前不产生core文件 2.ulimit -c unlimited 设置产生core文件 这种方法只是临时设置产生core文件 3.ec ...

  9. Netty的TCP粘包/拆包(源码二)

    假设客户端分别发送了两个数据包D1和D2给服务器,由于服务器端一次读取到的字节数是不确定的,所以可能发生四种情况: 1.服务端分两次读取到了两个独立的数据包,分别是D1和D2,没有粘包和拆包. 2.服 ...

  10. iOS5.0以上使用新浪微博开放平台OAuth 续(及解决登录无效问题)

    新浪微博开放平台为第三方应用提供了简便的合作模式,满足了手机用户和平板电脑用户随时随地分享信息的需求.通过调用平台的api即可实现很多微博上的功能. 本篇主要目的是记录新浪微博移动SDK iOS版本的 ...