Python装饰器学习

一、装饰器是什么
在代码运行期间不改变原函数定义的基础上,动态给该函数增加功能的方式,称之为装饰器。是一个很著名的设计模式

二、装饰器的使用范围
较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概况的讲,装饰器就是为已有的函数添加额外的功能。

三、装饰器和闭包
另外装饰器其实是个闭包,闭包就是:如果一个函数定义在另一函数的作用域内容,并且引用外层函数的变量,则该函数称为闭包。装饰器其实就是把一个函数作为参数后返回一个替代版的函数

装饰器的具体定义:

1、把要装饰的方法作为输入参数;

2、在函数体内可以进行任意的操作

3、只要确保最后返回一个可执行的函数即可(可以是原来输入的参数函数,也可以是一个新函数)

四、装饰器分类
无参数decorator:生成一个新的装饰器函数

有参数decorator:装饰函数先处理参数,再生成一个新的装饰器函数,然后对函数进行装饰

  无参装饰器
    #coding:utf-8
    __author__ = 'sunjinjuan'
    
    def log(fun):
        def wapper(*args,**karg):
            print "before %s called." %fun.__name__
            ret=fun(*args,**karg)
            print "after %s called" %fun.__name__
            return ret
        return  wapper
    
    @log
    def myfunc(a,b):
        print "myfunc(%s,%s) called" %(a,b)
        return a+b
    
    
    @log
    def myfunc1(a,b,c):
        print "myfunc1(%s,%s,%s) called" %(a,b,c)
        return a+b+c
    
    print myfunc(2,3)
    print myfunc(4,5)
    print myfunc1("a",'b','c')
    print myfunc1("dd","ff","gg")
    
    
    执行结果:
    D:\software\python27\python.exe D:/untitled/oopObject/test9.py
    before myfunc called.
    myfunc(2,3) called
    after myfunc called
    5
    before myfunc called.
    myfunc(4,5) called
    after myfunc called
    9
    before myfunc1 called.
    myfunc1(a,b,c) called
    after myfunc1 called
    abc
    before myfunc1 called.
    myfunc1(dd,ff,gg) called
    after myfunc1 called
    ddffgg



有参装饰器
    #coding:utf-8
    __author__ = 'sunjinjuan'
    
    def log(arg):
        def _log(fun):
            def _log(*args,**kwargs):
                print "before %s is called" %fun.__name__
                print "now params is%s" %arg
                ret=fun(*args,**kwargs)
                print "after %s is called" %fun.__name__
                return ret
            return _log
        return _log
    
    
    @log("myfun1")
    def fun1(a,b):
        print "fun1 is called"
        return a+b
    
    @log("myfun2")
    def fun2(a,b,c):
        print "fun2 is called"
        return a+b+c
    
    print fun1(2,3)
    print fun1(5,6)
    print fun2('a','b','c')
    print fun2("hello"," world","!")
    
    
    执行结果:
    D:\software\python27\python.exe D:/untitled/oopObject/test10.py
    before fun1 is called
    now params ismyfun1
    fun1 is called
    after fun1 is called
    5
    before fun1 is called
    now params ismyfun1
    fun1 is called
    after fun1 is called
    11
    before fun2 is called
    now params ismyfun2
    fun2 is called
    after fun2 is called
    abc
    before fun2 is called
    now params ismyfun2
    fun2 is called
    after fun2 is called
    hello world!



带类参数的装饰器
    mylocker.py文件内容:
    #coding:utf-8
    __author__ = 'sunjinjuan'
    
    class mylocker(object):
        def __init__(self,a,b):
            self.a=a;
            self.b=b
    
        @staticmethod
        def access():
            print "mylocker access is called"
    
        @staticmethod
        def release():
            print "mylocker release is called"
    
    
    class lockerex(object):
        @staticmethod
        def access():
            print "lockerex access is called"
    
        @staticmethod
        def release():
            print "lockerex release is called"
    
    def doc(cls):
        def _doc(fun):
            def _doc(*args,**kwargs):
                print "before %s called" %(fun.__name__)
                cls.access()
                try:
                    ret=fun(*args,**kwargs)
                finally:
                    cls.release()
                print "after %s called" %(fun.__name__)
    
                return ret
            return _doc
        return  _doc
    
    
    test11.py文件内容:
    #coding:utf-8
    __author__ = 'sunjinjuan'
    
    from mylocker import *
    
    @doc(mylocker)
    def fun1(a,b):
        print "fun1 is called"
        return a+b
    
    @doc(lockerex)
    @doc(mylocker)
    def fun2(a,b,c):
        print "fun2 is called"
        return a+b+c
    
    if __name__== "__main__":
        print fun1(1,2)
        print fun1(3,4)
        print fun2('a','b','c')
        print fun2('aa','bb','cc')
    
    
    
    执行结果:
    D:\software\python27\python.exe D:/untitled/oopObject/test11.py
    before fun1 called
    mylocker access is called
    fun1 is called
    mylocker release is called
    after fun1 called
    3
    before fun1 called
    mylocker access is called
    fun1 is called
    mylocker release is called
    after fun1 called
    7
    before _doc called
    lockerex access is called
    before fun2 called
    mylocker access is called
    fun2 is called
    mylocker release is called
    after fun2 called
    lockerex release is called
    after _doc called
    abc
    before _doc called
    lockerex access is called
    before fun2 called
    mylocker access is called
    fun2 is called
    mylocker release is called
    after fun2 called
    lockerex release is called
    after _doc called
    aabbcc

五、内置装饰器
staticmethod:定义实例方法为静态方法

classmethod:定义实例方法为类方法

property:对类属性的操作.以下是property装饰器的使用方法

(1)property方法,实现对属性变量的封装:

#coding:utf-8
__author__ = 'sunjinjuan'
class Person(object):

    def __init__(self,name):
        self.__name=name;

    def get_name(self):
        return self.__name

    def set_name(self,name):
        print(u"当前调用函数setName()")
        self.__name=name

    def del_name(self):
        print("remove...")
        del self.__name

    name=property(get_name,set_name,del_name,"name property docs")

bob=Person("bob")
print(bob.name)
bob.set_name("joe")
print(bob.name)
bob.del_name()
print(bob.name)

执行结果如下:

Python装饰器学习_第1张图片

(2)property装饰器
以下代码设置了birth是读写权限,age变量是只读权限

#coding:utf-8
__author__ = 'sunjinjuan'
import  datetime

class Student(object):

    @property
    def birth(self):
        return self._birth;

    @birth.setter
    def birth(self, birth):
        self._birth=datetime.datetime.strptime(birth,'%Y-%m-%d')
        print(u"设置学生出生时间:%s" %(self._birth))

    @property
    def age(self):
        currentTime=datetime.datetime.now()
        currentDate=currentTime.strftime("%Y-%m-%m")
        timedelta=datetime.datetime.strptime(currentDate,'%Y-%m-%d')-self._birth

        return  timedelta.days/365

s=Student()
s.birth="1999-01-01"
print s.birth

print u"学生当前年龄为:%s" %s.age

执行结果:

Python装饰器学习_第2张图片

六、装饰器的顺序
代码示例:

@A

@B

@C

def f():

pass

等价于:f=A(B(C(f)))

你可能感兴趣的:(python学习笔记)