[关闭]
@zzy0471 2018-04-12T11:55:40.000000Z 字数 1812 阅读 1015

Python乱记第十一:装饰器

Python


用法事例

Python在语法上支持装饰器模式。即:定义一个方法,该方法的参数是要被装饰的方法:

import time

def log(fun):
    def wrapper(*args, **kw): #这样写就可以接受任意参数了
        print(fun.__name__, 'is running at:', time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
        return fun(*args, **kw)
    return wrapper

@log
def function1():
    print('function 1')

@log
def function2():
    print('function 2')

function1()
function2()

运行结果:
image.png-29.7kB

加了@log就相当于这样调用:

import time

def log(fun):
    def wrapper(*args, **kw): #这样写就可以接受任意参数了
        print(fun.__name__, 'is running at:', time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
        return fun(*args, **kw)
    return wrapper

def function1():
    print('function 1')

wrapper = log(function1)
wrapper()

运行结果:

image.png-22.9kB

如果装饰器本身还有参数,那么就再包一层:

import time

def loglog(message):
    def log(fun):
        def wrapper(*args, **kw): #这样写就可以接受任意参数了
            print(message)
            print(fun.__name__, 'is running at:', time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
            return fun(*args, **kw)
        return wrapper
    return log

@loglog('hello')
def function1():
    print('function 1')

function1()

运行结果:

image.png-28kB

其实就相当于这样调用:

import time

def loglog(message):
    def log(fun):
        def wrapper(*args, **kw): #这样写就可以接受任意参数了
            print(message)
            print(fun.__name__, 'is running at:', time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
            return fun(*args, **kw)
        return wrapper
    return log

def function1():
    print('function 1')

log = loglog('hello')
wrapper = log(function1)
wrapper()

运行结果:

image.png-29.3kB

应用

我们可以自己使用装饰器实现自己的方法执行日志,此外,Python内置了一些非常有用的装饰器,比如:@property,使用该装饰器可以创建类的属性,从而就不用通过set_xxx和get_xxx这样的方式访问实例变量了:

class Person(object):

    def __init__(self, name, age):
        self._name = name
        self._age = age

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        self._name = value

    def get_age(self):
        return self._age

    def set_age(self, value):
        if not isinstance(value, int):
            raise ValueError('only need int')
        if value < 0 or value > 120:
            raise ValueError('bad value for age')
        self._age = value

p = Person('Joey', 30)
p.set_age(100)
p.name = 'Ross'

print(p.name)
print(p.get_age())

运行结果:
image.png-35.6kB

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注