是否可以测试对象属性是否使用描述符?

问题描述 投票:0回答:2

我不相信这是可能的,但我想我应该问一下,因为我是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

上旧式类的错误
python software-design descriptor
2个回答
2
投票

按照描述符对象的方法解析顺序搜索对象的类和超类:

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

0
投票

这是基于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相同,但内部逻辑不同。

© www.soinside.com 2019 - 2024. All rights reserved.