我已经开始在我编写的代码中更广泛地使用 python 描述符协议。通常,默认的 python 查找魔法是我想要发生的,但有时我发现我想要获取描述符对象本身而不是其__get__
方法的结果。想知道描述符的类型,或者存储在描述符中的访问状态,或者类似的东西。
我编写了下面的代码,以我认为正确的顺序遍历命名空间,并返回属性 raw,无论它是否是描述符。尽管我在标准库中找不到内置函数或其他东西来执行此操作,但我感到很惊讶——我认为它必须在那里,我只是没有注意到它或在谷歌上搜索了正确的搜索词。
python 发行版中的某处是否有已经执行此操作(或类似操作)的功能?
谢谢!
from inspect import isdatadescriptor
def namespaces(obj):
obj_dict = None
if hasattr(obj, '__dict__'):
obj_dict = object.__getattribute__(obj, '__dict__')
obj_class = type(obj)
return obj_dict, [t.__dict__ for t in obj_class.__mro__]
def getattr_raw(obj, name):
# get an attribute in the same resolution order one would normally,
# but do not call __get__ on the attribute even if it has one
obj_dict, class_dicts = namespaces(obj)
# look for a data descriptor in class hierarchy; it takes priority over
# the obj's dict if it exists
for d in class_dicts:
if name in d and isdatadescriptor(d[name]):
return d[name]
# look for the attribute in the object's dictionary
if obj_dict and name in obj_dict:
return obj_dict[name]
# look for the attribute anywhere in the class hierarchy
for d in class_dicts:
if name in d:
return d[name]
raise AttributeError
编辑,2009 年 10 月 28 日,星期三。
丹尼斯的回答给了我一个约定,可以在我的描述符类中使用来获取描述符对象本身。但是,我有一个完整的描述符类层次结构,我不想以样板文件开始每个函数 __get__
def __get__(self, instance, instance_type):
if instance is None:
return self
...
为了避免这种情况,我使描述符类树的根从以下继承:
def decorate_get(original_get):
def decorated_get(self, instance, instance_type):
if instance is None:
return self
return original_get(self, instance, instance_type)
return decorated_get
class InstanceOnlyDescriptor(object):
"""All __get__ functions are automatically wrapped with a decorator which
causes them to only be applied to instances. If __get__ is called on a
class, the decorator returns the descriptor itself, and the decorated
__get__ is not called.
"""
class __metaclass__(type):
def __new__(cls, name, bases, attrs):
if '__get__' in attrs:
attrs['__get__'] = decorate_get(attrs['__get__'])
return type.__new__(cls, name, bases, attrs)