我使用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)
输出:
9
似乎成功调用了方法__get__
和__set__
,但我不知道为什么没有输出消息is getting number
或is setting number
。
我不确定python是否会调用描述符方法。
我的问题是什么时候会调用描述符方法?
我总结了我的起源猜测:
获取
obj.prop
获取属性时,prop是另一个设置描述符a + 5
等值。如果a有描述符并将调用__get__
__get__
来获取函数体,然后调用__call__
来运行该函数。组
obj = 5
但我一定是错的,我需要有人告诉我正确的概念。
答案 0 :(得分:8)
您的描述符未被调用,并且无法编写描述符或其他任何内容来执行您想要的操作。
执行num = 2
时,您已丢弃Number
个对象并将变量num
设置为普通数字2.当您向其添加7时,它等于9,因为它只是一个常规数字。您的Number
课程没有任何参与。
描述符可让您了解执行obj.foo
或obj.foo = blah
时会发生什么。在这些情况下,foo
是描述符,而不是obj
,描述符仅在属性时才有效。没有办法改变obj = blah
时发生的事情,其中obj
是一个裸名称(即没有点或[]
)。关于你的猜测:
获取
obj.prop
和prop
是描述符,则会调用其__get__
。请注意,prop
是描述符,而不是obj
。a + 5
等值。如果a有描述符并且会调用__get__
__add__
魔术方法或其他运算符的类似方法覆盖此类行为__get__
来获取函数体,然后调用__call__
来运行该函数。
__call__
,则obj()
会调用其__call__
而不涉及任何描述符。组
obj = 5
obj.prop = 5
中,prop是描述符。底线是描述符仅在它们是类的属性时才起作用。只是在你试图做的时候创建一个“裸”描述符(即,做obj = SomeDescriptorClass()
)将不会做任何事情。
另外,作为旁注,描述符仅在新样式类上设置时才有效。如果你使用的是Python 2,这意味着持有描述符的类必须从object
继承。
答案 1 :(得分:3)
num = 2
使num
成为int
,但不再是Number
。
描述符必须是实例的属性,并且继承自object
。
class Number(object):
def __init__(self):
self.num = 0
def __get__(self, instance, obj):
print("is getting number")
return self.num
def __set__(self, instance, value):
print("is setting number")
self.num = value
# no need to define this for descriptor
def __str__(self):
return str(self.num)
class A(object):
num = Number()
n = A()
n.num = 5
print(n.num + 7)