gpt4 book ai didi

python - 让 python __set__ 工作

转载 作者:行者123 更新时间:2023-11-28 21:53:11 25 4
gpt4 key购买 nike

我只是想使用描述符模式,但似乎效果不佳。这是一个简短的例子(没有任何实际用途,只是为了展示):

class Num(object):
def__init__(self, val=0):
self.val = val
def __get__(self, instance, owner):
return self.val
def __set__(self, instance, val):
self.val = val
def __str__(self):
return "Num(%s)" % self.val
def __repr__(self):
return self.__str__()

class Test(object):
def __init__(self, num=Num()):
self.num = num

和测试:

>>>t = Test()
>>>t.num # OK
Num(0)
>>>t.num + 3 #OK i know how to fix that, but I thought __get__.(t.num, t, Test) will be called
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'Num' and 'int'
>>> t.num = 4 # why isn't __set__(t.num, t, 4) called here?
>>> t.num
4

我的误解是什么?

最佳答案

描述符只有在它们是类的属性时才起作用,而不是实例。如果您将类(class)更改为:

class Test(object):
num = Num()

. . .然后描述符将起作用。

但是,因为必须在类上设置描述符,这意味着描述符只有一个实例,所以描述符将其值存储在 self 上可能不是一个好主意.这些值将在该类的所有实例之间共享。相反,在 instance 上设置值。

另外,请注意您的 __str____repr__ 可能不会按照您的预期进行。调用 t.num 将激活描述符并返回其 val,因此 t.num 的结果将是普通数字 0,而不是 a Num 个实例。描述符的全部要点是透明地返回 __get__ 的结果,而不使描述符对象本身可见。

这里有一些说明性的例子:

>>> t1 = Test()
>>> t2 = Test()
>>> t1.num
0
>>> Test.num
0
# Accessing the descriptor object itself
>>> Test.__dict__['num']
Num(0)
>>> t1.num = 10
>>> t1.num
10
# setting the value changed it everywhere
>>> t2.num
10
>>> Test.num
10

使用描述符的替代版本:

class Num(object):
def __init__(self, val=0):
self.val = val

def __get__(self, instance, owner):
try:
return instance._hidden_val
except AttributeError:
# use self.val as default
return self.val

def __set__(self, instance, val):
instance._hidden_val = val

class Test(object):
num = Num()

>>> t1 = Test()
>>> t2 = Test()
>>> t1.num
0
>>> t1.num = 10
>>> t1.num
10
# Now there is a separate value per instance
>>> t2.num
0

关于python - 让 python __set__ 工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27029441/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com