什么时候调用python描述符方法?

Fre*_*ght 2 python descriptor

我使用python描述符模拟一些数据.

class Number:
    def __init__(self):
        self.num = 0 

    def __get__(self, instance, obj):
        print("is getting number")
        return self.number

    def __set__(self, instance, value):
        print("is setting number")
        self.number = value

    def __str__(self):
        return str(self.number)

num = Number()
num = 2 
print(num + 7)
Run Code Online (Sandbox Code Playgroud)

输出:

9
Run Code Online (Sandbox Code Playgroud)

它似乎成功地调用方法__get____set__,但我不知道为什么没有输出消息is getting numberis setting number.

我不确定python是否调用了描述符方法.

我的问题是什么时候会调用描述符方法?

我总结了我的起源猜测:

  1. 得到

    • 当用于obj.prop获取属性时,prop是另一个设置描述符的对象
    • 当计算某些表达式时应该得到诸如的值a + 5.如果a有描述符并将调用__get__
    • 如果一个对象模拟一个函数将首先调用__get__get函数体,然后调用__call__运行该函数.
    • 当对象出现在赋值语句的左侧时,如 obj = 5

但我一定是错的,我需要有人告诉我正确的概念.

Bre*_*arn 8

您的描述符未被调用,并且无法编写描述符或其他任何内容来执行您似乎想要的操作.

当你这样做时num = 2,你抛弃了你的Number对象并将变量num设置为普通数字2.当你向它添加7时,它等于9,因为它只是一个常规数字.你的Number班级没有任何参与.

描述符允许您勾选当您执行obj.foo或执行操作时发生的事情obj.foo = blah.在这些情况下,它是foo描述符,而不是obj,并且描述符仅在它是属性时才起作用.没有办法改变你做的事情obj = blah,obj一个裸名称(即没有点或[]).关于你的猜测:

  1. 得到

    • 当使用obj.prop来获取属性时,prop是另一个设置描述符的对象
      • 是的,基本上.当你这样做obj.prop并且prop是一个描述符时,它__get__就会被调用.请注意,这prop是描述符,而不是obj.
    • 当计算某些表达式时应该得到诸如的值a + 5.如果a有描述符并将调用__get__
      • 不可以.您可以使用__add__魔术方法或其他运算符的类似方法覆盖此类行为
    • 如果一个对象模拟一个函数将首先调用__get__get函数体,然后调用__call__运行该函数.
      • 我不明白这意味着什么,但我认为不是.如果对象定义__call__,则obj()调用它__call__而不涉及任何描述符.
    • 当对象出现在赋值语句的左侧时,如 obj = 5
      • 不.只有当描述符作为左侧的属性被访问时,例如obj.prop = 5,prop是描述符.

底线是描述符仅在它们是类的属性时才起作用.只是在你尝试做的时候创建一个"裸"的描述符(即,做obj = SomeDescriptorClass())将不会做任何事情.

另外,作为旁注,描述符仅在新样式类上设置时才起作用.如果您使用的是Python 2,这意味着持有描述符的类必须继承object.