【问题标题】:Precedence between non-data descriptor and instance entry in PythonPython中非数据描述符和实例条目之间的优先级
【发布时间】:2017-10-09 21:42:30
【问题描述】:

在 Python 3.6 文档的“Descriptor HowTo Guide" 的“描述符协议”段落中写着

如果一个实例的字典有一个同名的条目 非数据描述符,字典条目优先

也许我理解错了,但为什么在这个例子中非数据描述符优先于实例条目

class Descriptor:
    def __get__( self, instance, owner ):
        print( "__get__ is called" )
        return self.__dict__[self.name]


    def __set_name__( self, owner, name ):
        print( "__set_name__ is called" )
        self.name = name
        self.__dict__[name] = "Hello World"

d = Descriptor()

class MyClass:
    data = d

instance_of = MyClass()
instance_of.d = "Goodbye"

print()
print( instance_of.data )

我预计会输出Goodbye。但是输出了Hello World

【问题讨论】:

  • 1. 显示输出很有帮助。 2. 你的意思是instance_of.data = “Goodbye”? 3. 还有print(instance_of.data)?
  • 你还没有修正每一个错字。请参阅 2。一旦您这样做了,您将得到再见,因此您的问题将是多余的。
  • 你混淆了datad。您没有分配给您要读取的属性。投票结束是错字。
  • 这不仅仅是一个错字。这是对文档中描述符的“名称”含义的误解。参见示例中新的__set_name__ 方法的使用。
  • @Dunes 我不确定。描述符实例中设置的名称与另一个实例上的任一属性名称都不相同。

标签: python python-3.x descriptor


【解决方案1】:

这不是“名称”的意思。这里的“名称”指的是类__dict__ 和实例__dict__ 中的名称,并且不是描述符可能具有的任何名称属性。请参阅以下示例了解何时覆盖类描述符。

from pprint import pprint

class Descriptor:
    def __get__( self, instance, owner ):
        return "class"

class MyClass:
    data = Descriptor()

obj = MyClass()
# get the data descriptor's value
print(obj.data) # prints "class"

# set an instance attribute with the same name
obj.data = "instance"
print(obj.data) # prints "instance"

# print the variables of both class and instance
# -- both contain the name "data"
pprint(vars(MyClass)) # prints
# mappingproxy({'__dict__': <attribute '__dict__' of 'MyClass' objects>,
#               '__doc__': None,
#               '__module__': '__main__',
#               '__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
#               'data': <__main__.Descriptor object at 0x034BF1B0>})
print(vars(obj)) # prints
# {'data': 'instance'}

# delete the instance attribute and the descriptor becomes visible again
del obj.data
print(obj.data) # prints "class" again

【讨论】:

  • 在本节中写着“如果一个对象同时定义了 get__() 和 __set__(),它被认为是一个数据描述符”所以你的解释没有意义。 data 不是描述符,因为它至少没有定义 __get
  • 它是一个描述符,因为它确实定义了__get__。但它是非数据描述符而不是数据描述符。数据描述符也定义了__set__。您似乎也混淆了优先级。非数据描述符(没有__set__)被实例的__dict__ 否决。而数据描述符(带有__set__)会否决实例的__dict__
  • 最常见的非数据描述符是函数。这允许它们在将它们从实例中取出时返回绑定函数,但允许您通过将值设置为相同的名称来猴子修补对象。
  • 我很抱歉,但使用编程数据的一般术语没有任何定义。定义此方法的是类 Descriptor 或至少是对象 d。
猜你喜欢
  • 1970-01-01
  • 2015-08-29
  • 2012-10-12
  • 1970-01-01
  • 2015-08-01
  • 2019-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多