我已经开始在我写的代码中更广泛地使用python描述符协议。通常情况下,默认的python查找魔术就是我想要发生的事情,但有时候我发现我想获取描述符对象本身,而不是其__get__
方法的结果。想知道描述符的类型,或描述符中存储的访问状态,或者其他的东西。python属性查找没有任何描述符魔术?
我写了下面的代码来遍历我认为是正确的顺序的命名空间,并返回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
编辑周三,10月28日,2009年
丹尼斯的回答给了我一个约定,我的描述符类使用来获取描述对象本身。但是,我不得不描述符类的整个类层次,我不想开始与样板
def __get__(self, instance, instance_type):
if instance is None:
return self
...
为了避免这种情况每__get__
功能,我做了描述符类树的根继承以下内容:
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)
有时候你想要描述符对象?这违反了描述符的核心期望:它们应该看起来像属性。为什么要打破这种基本的期望?为什么要这样做?为什么创造如此复杂的东西 – 2009-10-27 01:34:41
我在做什么并不觉得*对我来说很复杂,但我想你可以说我正在试验这个设计。 在我目前的特殊情况下,我有一个描述符,它返回游戏中武器的强度。该值是描述符状态(武器强度)和实例(船舶的健康状况)的函数。有不同种类的武器;通常我只是想要价值结果,但在少数情况下,我需要知道它是什么样的武器 - 描述符的类型。 如果一个描述符的方法不是描述符协议的一部分,而你想调用它们呢? – 2009-10-27 02:06:52