gpt4 book ai didi

python - 为什么 Python 描述符适用于类级别属性而不适用于实例级别属性

转载 作者:太空宇宙 更新时间:2023-11-04 04:41:12 25 4
gpt4 key购买 nike

为什么 Python 描述符适用于类级属性而不适用于实例级属性。

class PropDescriptor:

def __init__(self,*args):
print("Init {} {}".format(type(self),args))
self.value = 0

def __get__ (self,instance,owner):
print("get using descriptor")
return instance.instance_att

def __set__(self, instance, value):
print("set using descriptor")
instance.instance_att = value


class TestClass:
class_att = PropDescriptor()

def __init__(self):
self.instance_att = PropDescriptor()



t = TestClass()
print("set instance level...")
t.instance_att = 3

print("\nget instance level...")
print(t.instance_att)

print("\nset class level...")
t.class_att = 4

print("\nget class level...")
print(t.class_att)

输出:

Init <class '__main__.PropDescriptor'> ()
Init <class '__main__.PropDescriptor'> ()
set instance level...

get instance level...
3

set class level...
set using descriptor

get class level...
get using descriptor
4

看起来描述符未用于 instance_att

我找到了这个 identical问题,但它并没有真正回答问题所有答案都引用帖子中的第二个问题。

The Python documentation指定:

Instance Binding

If binding to an object instance, a.x is transformed

into the call: type(a).__dict__['x'].__get__(a, type(a)).

但是:(我的代码等效)语句的第一部分 type(t).__dict__["instance_att"],引发 KeyError 作为 type(t).__dict__ 没有这样的属性。它是一个实例级别的att。不是吗?

我错过了什么?

最佳答案

我现在回复有点晚了,但我会尽力解释。问题的两个部分的答案在于 python 内部实现属性查找和设置的方式。

<强>1。为什么不为实例级属性调用描述符?

一旦您理解了 a.x = somevalue 的内部转换方式,这个问题的答案就很简单了。当您使用 dot 运算符设置属性时,例如 a.x="somevalue" 它转换为 a.__setattribute__(x, somevalue) 进一步转换为type(a).__dict__['x'].__set__(x, somevalue).

现在考虑您的示例 self.instance_att 是在 __init__ 中定义的,因此它不存在于 type(a).__dict__ 中这是在类级别定义的属性字典,因此永远不会调用描述符的 __set__

<强>2。为什么描述符仅在类级别定义?

我不是百分百确定,但这是我的理解,因为 __getattribute____setattribute__ 是如何实现的,如果在实例级别定义描述符将根本不起作用(如上所述),因此它们仅被定义为类属性。

此外,我相信要使描述符适用于实例属性,您必须为该类覆盖 __getattribute____setattribute__。这就是被覆盖的最简单版本 __getattribute__ 的样子。

def __getattribute__(self, attr):
attr_val = super().__getattribute__(attr)
attr_type = type(attr_val)
if hasattr(attr_type, '__get__'):
return attr_type.__get__(attr_val, self, type(self))
return attr_val

这是相同的演示

$ python3 -i instance_descriptors.py
>>> t = TestClass()
>>> t.instance_att
get using descriptor
200
>>>

以类似的方式,您还需要覆盖 __setattribute__ 才能使属性设置生效。

希望对您有所帮助!

我强烈建议您阅读以下描述符的官方 Python 文档,以完整理解该概念。

Descriptors howto

关于python - 为什么 Python 描述符适用于类级别属性而不适用于实例级别属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50556491/

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