Python 中的装饰器

来源:转载


对于装饰器的理解,可以查看这个文档。


在文本中,我们主要来学习 @property 的使用。在python中,我们需要对外暴露一个成员变量的时候,我们往往需要对外部输入的值进行判断,以确保是符合我们的期望的。


class Student(object):
age = 20

student = Student()
print student.age
student.age = "hello"

上述这种写法虽然可以取到age属性,但是同时也可以对age设置任意值。所以并不合理。


那怎么解决了,我们可以把age变成私有的成员变量。然后写一个getter用于供外部取得age值;一个setter函数用于供外部设置age值,并对age值进行一定的判断。


例如:


class Student(object):
def __init__(self):
self._age = None
def age_getter(self):
return self._age
def age_setter(self, age):
if isinstance(age, str) and age.isdigit():
age = int(age)
else:
raise ValueError("age is illegal")
if isinstance(age,int):
self._age = age

那么我就需要 student.age_getter() 取得 agestudent.age_setter() 设置 age 值。但是这样实现了功能,但是的确使得调用变得比较麻烦。有什么地方可以改进吗?


这个时候我们可以在 gettersetter 后面定义一个成员变量 age 。例如:


age = property(age_getter, age_setter)

这样我们就可以把age当成一个Student的属性来调用和赋值了。
例如:


student.age = "20"
print student.age

你觉得python只能这么写getter和setter了,那就图样图森破了。python还有逆天的装饰器来实现getter、setter、和deleter。
例如:


class Student(object):
def __init__(self):
self._age = None
@property
def age(self):
return self._age
@age.setter
def age(self, age):
if isinstance(age, int):
self._age = age
return
if isinstance(age, str) and age.isdigit():
age = int(age)
self._age = age
else:
raise ValueError("age is illegal")
@age.deleter
def age(self):
del self._age

student = Student()
student.age = 20
print student.age
del student.age

上面的例子中用@property、x.setter x.deleter实现了属性的读取、赋值、和删除。当然您也可以只是实现其中的一个或者几个。


但有时候我们会使用 @wraps 装饰器,它的作用又是什么呢?


使用装饰器会产生我们可能不希望出现的副作用,例如:改变被修饰函数名称,对于调试器或者对象序列化器等需要使用内省机制的那些工具,可能会无法正常运行;其实调用装饰器后,会将同一个作用域中原来函数同名的那个变量(例如下面的func_1),重新赋值为装饰器返回的对象;使用@wraps后,会把与内部函数(被修饰函数,例如下面的func_1)相关的重要元数据全部复制到外围函数(例如下面的decorate_inner)


from functools import wraps

def decorate(func):
print('running decorate', func)
@wraps(func)
def decorate_inner():
print('running decorate_inner function', decorate_inner)
return func()
return decorate_inner

<a href="http://www.jobbole.com/members/decorate">@decorate</a>
def func_1():
print('running func_1', func_1)

if __name__ == '__main__':

func_1()

#返回值
running decorate <function func_1 at 0x7f145d2c2268>
running decorate_inner function <function func_1 at 0x7f145b9731e0>
running func_1 <function func_1 at 0x7f145b9731e0>

来源:
segmentfault
jobbole




分享给朋友:
您可能感兴趣的文章:
随机阅读: