在代码运行期间动态增加功能的方式,称之为“装饰器”。装饰器本质是高阶函数, 就是将函数作为参数进行相应运作,最后返回一个闭包代替原有函数. 装饰器本质就是将原函数修饰为一个闭包(一个返回函数).
装饰器在python中在函数/对象方法定义前使用@
符号调用. 装饰器可以在函数运行前进行一些预处理, 例如检查类型等.
@dec1@dec2(arg1,arg2)def test(arg): pass
以上代码等于dec1(dec2(arg1,arg2)(test(arg)))
例如:
def log(func): def wrapper(*args, **kw): print 'call %s():' % func.__name__ return func(*args, **kw) return wrapper@logdef now(): print '2015-10-26' return "done"now()# 实际调用wrapper()#>>> call now()#>>> 2015-10-26
机制就是,调用now()实际调用log(now)() (前面@
写法后,实际运行now=log(now)),也就是运行了wrapper(),并把now函数原有参数传递给了wrapper函数. wrapper在运行时,加入了新的处理print 'call %s():' % func.__name__
一句, 并运行相应传递参数的func(*args,**kw)
并把原有结果返回.
now=log(now) #->now=wrapperresult=now() #->wrapper()>>>call now() #-> wrapper修饰部分>>>2015-10-26 #-> 原函数部分执行部分print result>>>done #-> 原函数的返回部分
所以装饰器机制简单地说就是要:
@log
部分,now=log(now)
)def wrapper()..return wrapper
部分)def log(text): def decorator(func): def wrapper(*args, **kw): print '%s %s():' % (text, func.__name__) return func(*args, **kw) return wrapper return decorator@log('execute')def now(): print '2015-10-26' return "done"now()#>>> excute now()#>>> 2015-10-26
装饰器本身可以传入参数.不要小看这个传入参数, 传入的参数因为占据了本身装饰器的参数, 所以需要新的一层装饰器来处理原函数. 上述机制:
now=log('execute')(now) #-> now=wrapper#或者可以说f=log('execute') -> f=decorator# f(now) -> decorator(now) -> wrapper# now=wrapperresult=now() #wrapper()
实际now=log('execute')(now)
两个参数表就是执行了一次闭包decorator(now).执行该闭包后返回的才是真正的装饰器wrapper.
两层闭包的机制可以保证传递参数给内在的装饰器wrapper.第一层将参数传进行生成第一层闭包对应返回函数,第二层则将该参数继续留给真正的装饰器闭包.
在以上装饰器中, 其实质都是now=wrapper
, 此时我们要是输出now.__name__
得到的将是装饰器wrapper的名字.可以用wrapper.__name__=func.__name__
加在装饰器内部进行原函数信息的继承, 也可以使用functools.wraps
来实现.
import functoolsdef log(func): @functools.wraps(func) def wrapper(*args, **kw): print 'call %s():' % func.__name__ return func(*args, **kw) return wrapper
对于带参数的装饰器, 依然将@functools.wraps(func)
写在实质装饰器wrapper前面.
其机制:
wrapper=functools.wraps(func)(wrapper) #将原函数func信息给返回函数f=functools.wraps(func), f 闭包含有相应func信息.#用f 返回函数来修饰wrapper, 此时实际可以将wrapper的一些信息替换为原函数
对于很复杂的体系, 需要经常定义一些高阶函数对新函数进行一系列处理, 此时定义装饰器就可以省很多功夫. 但缺点是初学比较难以理解, 要对OOP十分熟悉.
该装饰器是python内置的,是类中一个高级用法,作用是将一个方法名变成一个对象属性. 类需要继承于object相应的类.
构建相应@property def prop(self):return self._prop
就可以直接obj.prop
来将方法变成获取对象属性的调用形式.而相应@prop.setter def prop(self,value): self._prop=value
就可以实现obj.prop=value
将方法转为对象属性的赋值.而且好处还可以在此加入属性的值的检查. obj._prop只是相应储存的储存地方,名字也是无限制的.
不定义setter而只定义property的话,该属性就是只读的不能修改的!!
例如:
class Student(object): @property def score(self): return self._score @score.setter def score(self, value): if not isinstance(value, int): raise ValueError('score must be an integer!') if value < 0 or value > 100: raise ValueError('score must between 0 ~ 100!') self._score = value @property def fail(self): return True if (self.score <60) else False # (self.score <60) and return True or return Falses = Student()s.score = 60 # OK,实际转化为s.set_score(60)s.score # OK,实际转化为s.get_score()### 60s.score = 9999### Traceback (most recent call last):### ...### ValueError: score must between 0 ~ 100!s.fail### Falses.fail=True### Traceback (most recent call last)### ...### AttributeError: can't set attribute
本博文已合并到Python语法汇总中, 不再更新.
联系客服