property装饰器的描述器实现
引言
在Python官方文档中的 描述器使用指南 一篇中,给出了常用装饰器 property
的Python代码模拟实现,且这个实现是基于描述器原理的。
在本文中,作者将利用这段代码,向你展示描述器的实际运行原理。
装饰器基本内容
首先我们回忆一下装饰器的有关内容。
装饰器本质是个返回函数的函数,表现为数学概念中的复合函数 (g o f)(x) -> g(f(x))
下面我们用伪代码再补充一些容易产生疑问的情况。
多层装饰器的含义
@dec2
@dec1
def func(arg1, arg2, ...):
pass
↑↑↑ 等价于 ↓↓↓
func = dec2(dec1(func))
带参装饰器的含义
@decomaker(argA, argB, ...)
def func(arg1, arg2, ...):
pass
↑↑↑ 等价于 ↓↓↓
func = decomaker(argA, argB, ...)(func)
类装饰器和函数装饰器是一致的,只相当于将 func 代表的函数换做 cls 代表的类罢了,故这里不再多做涉及。
如果对于装饰器还有问题的话建议阅读一下官方PEP,可以使用Google翻译,效果还是不错的。
PEP 318 – Decorators for Functions and Methods
PEP 3129 – Class Decorators
描述器基本内容
这里推荐我针对描述器撰写的上一篇博文 Python描述器学习指南
官方模拟的源码
我们首先看一下用描述器模拟实现装饰器 property
的源代码。
(这里大概看一下就好,我们后文再详细分析)
class Property:
"Emulate PyProperty_Type() in Objects/descrobject.c"
def __init__(self, fget=None, fset=None, fdel=None, doc=None):
self.fget = fget
self.fset = fset
self.fdel = fdel
if doc is None and fget is not None:
doc = fget.__doc__
self.__doc__ = doc
def __get__(self, obj, objtype=None):
if obj is None:
return self
if self.fget is None:
raise AttributeError("unreadable attribute")
return self.fget(obj)
def __set__(self, obj, value):
if self.fset is None:
raise AttributeError