1. 修饰器
1.1 函数作为修饰器
python的修饰器(decorator)是一项重要的语法,能够发挥出重要作用。理解修饰器的关键是认识到修饰器其实就是给函数包裹了一层函数。以下面这段代码为例子:
@myDecorator
def aFunction():
print "inside aFunction"
当编译aFunction函数时,编译器会先经过myDecorator函数,进而返回一个函数,然后把这个函数赋值给aFunction。所以,在运行aFunction()时,就相当于运行了myDecorator里面的东西。如果我们直接打印aFunction函数对象,会发现修饰前后是不同的。
为了保证修饰前后是相同的,我们可以使用一个修饰器@wraps。该修饰器可以保留函数的元信息,方便后期debug。[1]
from functools import wraps
def tags(tag_name):
def tags_decorator(func):
@wraps(func)
def func_wrapper(name):
return "<{0}>{1}</{0}>".format(tag_name, func(name))
return func_wrapper
return tags_decorator
@tags("p")
def get_text(name):
return "Hello "+name
print(get_text("John"))
print(get_text)
print(get_text.__name__)
# the result is (without @wraps)
<p>Hello John</p>
<function tags.<locals>.tags_decorator.<locals>.func_wrapper at 0x7fa8b755e9d8>
func_wrapper
# the result is (with @wraps)
<p>Hello John</p>
<function get_text at 0x7f2c2d4059d8>
get_text
可以看出,加入了@wraps以后,get_text函数的元信息被保留了。
1.2 类作为修饰器
利用类来作为修饰器其实更好理解修饰器机理。能够更加看清楚修饰器构建以及作用的时间。[2]
class NewDecorator(object):
def __init__(self, f):
print("inside myDecorator.__init__()")
# f() # Prove that function definition has completed
self.f = f
def __call__(self, *args, **kwargs):
print("inside myDecorator.__call__()")
result = self.f(*args, **kwargs)
return result
@NewDecorator
def add_num(a, b):
return a+b
print(add_num)
print("after the decorator")
result = add_num(1,3)
print(result)
# the result is
inside NewDecorator.__init__()
<__main__.NewDecorator object at 0x7f7ee79190f0>
after the decorator
inside NewDecorator.__call__()
4
修饰器其实就是给函数加上了一个函数,这一部分在构造函数里面完成,同时也会返回一个函数给原来函数,这里就是__call__函数。
2. @property修饰器
property修饰器是python类中比较常见的一个修饰器,其主要的功能就是为了方便管理类中的成员变量。
class Celsius:
def __init__(self, temperature = 0):
self._temperature = temperature
def to_fahrenheit(self):
return (self.temperature * 1.8) + 32
@property
def temperature(self):
print("Getting value")
return self._temperature
@temperature.setter
def temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
print("Setting value")
self._temperature = value
主要是为了方便赋值,并且可以在赋值或是取值时做类型检测和有效性判断 。[3]
参考:
[1] https://www.thecodeship.com/patterns/guide-to-python-function-decorators/
[2] https://www.artima.com/weblogs/viewpost.jsp?thread=240808
[3] https://www.programiz.com/python-programming/property