澄清几对python描述符

时间:2013-08-21 21:28:37

标签: python

Descriptors HowTo

有人可以通过一个例子来帮助我理解这个吗?:

如果实例的字典具有与数据描述符同名的条目,则数据描述符优先。如果实例的字典具有与非数据描述符同名的条目,则字典条目优先。

实现通过优先级链工作,该优先级链使数据描述符优先于实例变量,实例变量优先于非数据描述符,并为_ getattr_ ()分配最低优先级(如果提供)。

特别是我不明白的是:

  1. 实例的字典如何具有与描述符同名的条目。你能举个例子吗?

  2. 您还可以举个例子,数据描述符优先于实例变量,实例变量优先于非数据描述符等吗?

  3. 同样在下面的代码中,我很惊讶地看到test.xlass中的self.x调用__ set __: 我相信这种行为是因为上述链接中的这种解释:

    对于对象,机器在对象.__ getattribute __()中,它将b.x转换为类型(b)。 __ dict __ ['x']。 __ get __(b,type(b))。对吗??

        #! /usr/bin/env python
        class descclass(object):
    
                def __init__(self, value):
                        print "in desc init"
                        self.value = value
                        print "out of desc init"                
    
                def __get__(self, inst, insttype):
                        print "in desc get"
                        return self.value
    
                def __set__(self,inst, val):
                        print "in desc set"
                        self.value = val
    
        class testclass(object):
    
                x = descclass(100)
                print "desc created"
    
                def __init__(self, val):
                        print "in testclass init"
                        self.x = val  # this invokes __set__ on descriptor in x
                        print "out of testclass init"
    
        if __name__ == '__main__':
    
                t = testclass(45)
                print t.x
                print vars(t)
                print vars(testclass)
    

2 个答案:

答案 0 :(得分:4)

这是一个例子。

# Not a data descriptor because it doesn't define __set__
class NonDataDescriptor(object):
    def __get__(self, obj, objtype):
        return 3

class Namespace(object):

    # Data descriptor - defines both __get__ and __set__
    @property
    def foo(self):
        return 3

    bar = NonDataDescriptor()

x = Namespace()
x.__dict__['foo'] = 4  # We bypass the foo descriptor's __set__ here,
x.bar = 4              # but there's no bar setter, so this one goes to the dict

# x now has foo and bar descriptors and __dict__ entries

print x.foo  # prints 3 - data descriptor wins over instance __dict__ entry
print x.bar  # prints 4 - instance __dict__ entry wins over non-data descriptor

答案 1 :(得分:1)

描述符始终是的一部分;实例有自己的属性,通常它们优先于类的任何属性。

数据描述符只是具有__get____set__方法的描述符。所以Python做到了这一点:

  1. 查看是否有数据描述符;带有两个钩子的描述符。
  2. 在实例
  3. 上查找属性
  4. 在类
  5. 上查找常规(非数据)描述符
  6. 回退到班级的常规属性
  7. 第3点和第4点真的是一回事;描述符是具有特定方法的类属性;所以当该属性上没有描述符挂钩时,第4点确实是第3点。