【问题标题】:Why are Python descriptor methods not invoked when called with obj.x syntax?为什么在使用 obj.x 语法调用时不调用 Python 描述符方法?
【发布时间】:2015-01-26 18:16:27
【问题描述】:

我在这里有一个描述符类X。我尝试在另一个类Y 中使用描述符X

class X:
    def __init__(self, value):
        self.value = value

    def __get__(self, instance, owner):
        print('#### X.__get__ ####')
        return self.value

    def __set__(self, instance, value):
        print('#### X.__set__ ####')
        self.value = value

class Y:
    def __init__(self):
        self.x = X(10)

y = Y()
print(y.x)
y.x = 20

我希望语句print(y.x) 会调用x.__get__,语句y.x = 20 会调用x.__set__,但它没有发生。当我运行上面的程序时,我只是得到这个输出。

<__main__.X object at 0x7fc65f947950>

为什么没有调用描述符方法?

【问题讨论】:

  • @jonrsharpe 我不认为__getattr__y.x 会调用x.__getattr__。相反,y.x 将调用 y.__getattr__。但是,我试图用y.x 调用x.__getattr__,这是描述符应该做的。
  • @martineau 谢谢。修好了。

标签: python python-3.x descriptor


【解决方案1】:

要调用描述符协议方法,您需要将描述符实例(在您的情况下为X())放在Y 上,而不是放在实例上。 Raymond Hettinger 在Descriptor HowTo Guide 中对此进行了详细描述:

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

注意b.x是如何转化为type(b)的dict访问得到的描述符的调用。 Y 类应如下所示:

class Y:
    x = X(10)

但是,由于X 的单个实例将被Y 的所有实例共享,因此需要修改X 描述符类以从instance 而不是@987654335 获取和设置值@。

【讨论】:

  • 换句话说,Y 需要看起来像这样:class Y: \n x = X(10)
  • @Asad 还需要对X 进行修改,否则所有Y 实例将共享相同的x
  • @jonrsharpe 他们将共享相同的X 实例,但我假设您可以让它返回instance 的某些属性而不是self,这样返回的值对于Y 实例。
  • @Asad 是的,就是需要修改
  • @jonrsharpe 好点,我已经更新了答案以指出陷阱。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-27
  • 1970-01-01
  • 2010-10-17
  • 1970-01-01
相关资源
最近更新 更多