我不相信这是可能的,但我想我应该问一下,因为我是Python新手。给定一个具有属性的对象,其值由描述符处理;是否有可能知道涉及给定的描述符类型?
描述符示例:
class Column(object):
def __init__(self, label):
self.label = label
def __get__(self, obj, owner):
return obj.__dict__.get(self.label)
def __set__(self, obj, value):
obj.__dict__[self.label] = value
测试对象:
class Test(object):
name = Column("column_name")
def add(self):
print self.name.__class__
执行此操作:
my_test = Test()
my_test.name = "myname"
my_test.add()
这给出了:
<type 'str'>
这是值“myname”的数据类型,是否可以测试 isinstance(self.name, Descriptor) - 这返回 false,但我希望它返回 true - 或类似的东西?
编辑 - 删除了
Test
上旧式类的错误
按照描述符对象的方法解析顺序搜索对象的类和超类:
def find_descriptor(instance, attrname):
'''Find the descriptor handling a given attribute, if any.
If the attribute named attrname of the given instance is handled by a
descriptor, this will return the descriptor object handling the attribute.
Otherwise, it will return None.
'''
def hasspecialmethod(obj, name):
return any(name in klass.__dict__ for klass in type(obj).__mro__)
for klass in type(instance).__mro__:
if attrname in klass.__dict__:
descriptor = klass.__dict__[attrname]
if not (hasspecialmethod(descriptor, '__get__') or
hasspecialmethod(descriptor, '__set__') or
hasspecialmethod(descriptor, '__delete__')):
# Attribute isn't a descriptor
return None
if (attrname in instance.__dict__ and
not hasspecialmethod(descriptor, '__set__') and
not hasspecialmethod(descriptor, '__delete__')):
# Would be handled by the descriptor, but the descriptor isn't
# a data descriptor and the object has a dict entry overriding
# it.
return None
return descriptor
return None
这是基于Python官方文档,所以我相信它更正确。我采用了
__getattribute__
的参考 Python 实现,然后进行了修改以仅返回描述符:
def find_descriptor(obj, name:str):
""" Find the descriptor, if any, an attribute retrieval on an instance would go through
:param obj: instance object
:param name: attribute which would be retrieved
:returns: unbound descriptor ``__get__``, or ``None`` if no descriptor would be used
"""
# lookup attribute in class hierarchy
for base in type(obj).__mro__:
base_dict = vars(base)
if name in base_dict:
# we look for descriptor interface on value's class, not value itself
value_clazz = type(base_dict[name])
descr = getattr(value_clazz, '__get__', None)
if descr:
# data descriptor?
if (hasattr(value_clazz, '__set__') or hasattr(value_clazz, "__delete__")):
return descr
# instance variable can be used instead?
if hasattr(obj, '__dict__') and name in vars(obj):
return
# non-data descriptor?
# if None, it indicates a class variable
return descr
# else, descriptor attribute not found
# (could still be an instance variable, but we don't care about that)
外层循环与@user2357112相同,但内部逻辑不同。