如何使用 __get__ 和 __set__(python 描述符)
How to use __get__ and __set__ (python descriptors)
我刚开始使用描述符,我想我对它们的工作原理有很好的理解,但我遇到了一个问题,我不确定如何解决它。
代码
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
.
谁能告诉我为什么没有出现错误?
来自 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
正在设置 class 属性,而不是实例属性。如果你确实使用了一个实例(没有先设置 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__
行为,则 class 本身需要是 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
我刚开始使用描述符,我想我对它们的工作原理有很好的理解,但我遇到了一个问题,我不确定如何解决它。
代码
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
.
谁能告诉我为什么没有出现错误?
来自 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
正在设置 class 属性,而不是实例属性。如果你确实使用了一个实例(没有先设置 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__
行为,则 class 本身需要是 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