【问题标题】:Is it possible to test if object property uses a descriptor?是否可以测试对象属性是否使用描述符?
【发布时间】:2014-02-23 00:57:11
【问题描述】:

我不相信这是可能的,但我想我会问,因为我是 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 上旧式类的错误

【问题讨论】:

  • my_test.name 通常应该分配给列对象吗?
  • 不,my_test.name 是 Test() 对象的属性。描述符将用于确保名称有效。我使用描述符而不是@property 来减少代码,因为它将在许多地方使用。理想情况下,我想知道 my_test.name 使用了列描述符。但是,我不确定这是否可能..
  • @Matt 您是否试图确定描述符覆盖了哪些方法,或者对象的类是否是描述符?
  • @Mike 我正在尝试确定属性是否使用特定描述符来设置值。
  • 好吧,我不知道你有什么问题,但对我来说foo = Column("bar") ; isinstance(foo,Column) 返回True(用py2和py3测试)并且foo.__class__<class '__main__.Column'>

标签: python software-design descriptor


【解决方案1】:

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

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

【讨论】:

  • 是的,这行得通!看起来我需要通过方法解析顺序。我想我只是在阅读价值类,而不是通过 mro 工作。非常感谢!
  • 此函数错误地返回 descriptor 而不是 Nonedescriptor 在其 实例 中带有 '__get__''__set__''__delete__' 条目字典,并且在其类字典或其祖先中没有一个。为了纠正这个问题,hasattr 应该被重新定义,以便仅在类字典及其祖先而不是实例字典上查找条目。我已经更新了答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-16
  • 2017-03-16
  • 2013-07-30
  • 2012-02-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-20
相关资源
最近更新 更多