【问题标题】:How does the data descriptor priority work in python数据描述符优先级在python中是如何工作的
【发布时间】:2013-02-11 03:17:29
【问题描述】:

我从网上读到这个东西

对于对象,机器位于object.__getattribute__which 将b.x 转换为type(b).__dict__['x'].__get__(b, type(b)).

实现是通过一个优先链进行的 数据描述符优先于实例变量实例变量优先于非数据描述符,如果提供,则将最低优先级分配给 getattr。 p>

我不明白“数据描述符优先于实例变量”和“实例变量优先于非数据描述符”是什么意思

谁能给我举个例子,这实际上是如何工作的?我想看看代码中有什么优先级

【问题讨论】:

标签: python


【解决方案1】:

每个对象都有一个属性字典,其中包含它的变量和函数。参考这些词典:

If an instance’s dictionary has an entry with the same name as a data descriptor,    
the data descriptor takes precedence. If an instance’s dictionary has an entry with
the same name as a non-data descriptor, the dictionary entry takes precedence.

这就是他们所说的。

显示这个:

#data descriptor
class A(object):
   def __get__(self, obj, type):
       print "hello from get A"
   def __set__(self, obj, val):
       print "hello from set A"
#non data descriptor
class B(object):
   def __get__(self, obj, type):
       print "hello from get B"

class C(object):
   #our data descriptor
   a = A()
   #our non data descriptor
   b = B()

>>> c = C()
>>> c.a
hello from get A
>>> c.b
hello from get B
>>> c.a = 0
hello from set A
>>> c.a          #notice after reassignment, A.__get__ is still called
hello from set A
>>> c.b = 0     #instance variable with the same name as the non data-descriptor
>>> c.b         #notice how B.__get__ isn't called anymore
0

基本上,当__get____set__ 是用户为对象(数据描述符)定义时,它们将被调用而不是默认方法。如果用户只为对象(非数据描述符)定义了__get__,则实例可以重新分配实例变量。

所以当调用g.x = 0 时:如果x 是数据描述符,则调用x 的用户定义的__set__ 方法,当x 是实例变量或非数据描述符时调用默认行为。

使用数据描述符,该类控制对变量的所有访问和修改。 对数据描述符类型变量的所有访问都将通过__get____set__。所以c.a = 0 调用A.__set__ 并且 c.a 改变了类定义它的方式。无法创建非 A 类型的实例变量“c.a”。

使用非数据描述符,类只控制访问,所以当c.b = 0被调用时,由于__set__没有被定义,一个新的实例变量被创建(默认行为) .设置变量时没有用户定义的行为,因此您可以创建具有相同名称的实例变量,而无需 __get__ 行为。

他们所说的优先级是两者的动态。数据描述符将始终调用__get____set__,因此不能创建具有相同名称的实例变量。非数据描述符只会调用__get__,直到创建了同名的实例变量。

【讨论】:

  • 我再次不清楚。你说 If x is data descriptor 所以这意味着如果 x 没有 __get____set__ 定义。正确的?所以这意味着 x 将永远是一个类,因为我只能在类中定义方法。如果x 是实例变量,那么我如何在变量中定义像__get__ 这样的方法。这让我很困惑
  • 是的,数据描述符的定义是它定义了__get____set__。非数据描述符只定义了__get__。实例变量可以是类的对象,例如c.a = MyClass()。更多的是关于数据描述符如何使用__set__ 定义修改,以及非数据描述符如何不进行用户定义修改。我进行了编辑以尝试提高清晰度。
  • 注意:具有__slots__ 属性的类的对象没有属性字典。
猜你喜欢
  • 2015-08-29
  • 1970-01-01
  • 1970-01-01
  • 2018-06-08
  • 2015-08-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 2012-05-26
相关资源
最近更新 更多