如何使用uuu get_uuu和uuu set_uuu(python描述符)

2024-06-17 15:22:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我不熟悉使用描述符,我想我对它们的工作原理有很好的理解,但我遇到了一个问题,我不知道如何解决它

代码

class Foo:
    class Bar:
        def __get__(self,instance, owner):
            return 10
        def __set__(self,instance,value):
            raise Exception
    bar=Bar()

print(Foo.bar)
Foo.bar=5
print(Foo.bar)

输出

>>> 10
>>> 5

出于测试目的,我试图将bar设为常量,我知道property装饰器,但我更喜欢使用描述符

首先,我打印出bar的值,以查看__get__是否有效-它确实有效,输出为10

但是,当我将5分配给bar时,预期的结果将是一个异常,但实际情况是5被分配给bar,尽管指定了__set__,所以当我再次打印时,第二个输出是5

有人能告诉我为什么没有出现错误吗?


1条回答
网友
1楼 · 发布于 2024-06-17 15:22:47

the docs

object.__set__(self, instance, value)

Called to set the attribute on an instance instance of the owner class to a new value, value.

在代码中,Foo.bar = 5设置的是类属性,而不是实例属性。如果您确实使用了实例(没有首先设置Foo.bar = 5,这会覆盖您的描述符),那么您会得到预期的异常:

>>> f = Foo()
>>> f.bar
10
>>> f.bar = 5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in __set__
Exception

如果希望在设置class属性时应用__set__行为,则类本身需要是使用描述符的metaclass的实例:

class FooMeta(type):
    class Bar:
        def __get__(self,instance, owner):
            return 10
        def __set__(self,instance,value):
            raise Exception
    bar = Bar()

class Foo(metaclass=FooMeta):
    pass

测试:

>>> Foo.bar
10
>>> Foo.bar = 5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in __set__
Exception

相关问题 更多 >