gpt4 book ai didi

python - 使用类名在Python中设置描述符属性的值

转载 作者:行者123 更新时间:2023-12-01 06:56:48 25 4
gpt4 key购买 nike

我试图了解描述符在 Python 中的工作原理。我有下面的代码片段。

>>> class D(object):
def __get__(*_):
print('get called')
def __set__(*_):
print('set called')
>>>
>>> class Person(object):
name = D()

>>>
>>> jane = Person()
>>> jane.name
get called
>>> jane.name = 'Janny'
set called
>>> Person.name
get called
>>> Person.name = 'Jack'
>>>

当使用类名访问描述符属性name时,即调用Person.name get方法。但是,当我尝试使用相同的方式设置值时,即 Person.name = 'Jack' 设置不会被调用。在这里,我期待着 set 被调用。

我无法理解这种行为。

我使用的是 Python 3.8。

最佳答案

装饰器是在对象的类型上定义的,例如在对象 jane 的示例中,name 引用的描述符必须以 jane 的类型定义,即在类 的主体上定义人。因此,对于类,需要在类的元类中定义描述符(因为类是其元类的实例),以便为类对象上的给定属性查找调用描述符。

在您的示例中,jane.namejane.name = 'Janny' 作为 name 引用的描述符在类 Person 的主体,即它存在于 Person.__dict__ 上(这是一个 mappingproxy 对象,并且是只读的)。接下来,Person.namePerson.__dict__ 上找到了属性,并发现它具有 __get__ 属性,因此它是一个描述符,因此称为 >__get__ 用于检索值。现在,当您设置 Person.name = 'Jack' 时,它会将 name 属性设置为通过 Person 引用字符串对象 Jack .__setattr__,删除之前对描述符 D 的引用。所以现在所有对 name 的引用,例如如果您执行jane.name/Person.name,您将得到字符串Jack

<小时/>

以下示例说明了如何通过在元类中应用描述符来实现所需的行为:

In [15]: class FooDec: 
...: def __get__(self, instance, owner=None):
...: print(f'__get__ called with: instance: {instance}, owner: {owner}')
...: def __set__(self, instance, value):
...: print(f'__set__ called with: instance: {instance}, value: {value}')
...:

In [16]: class Meta(type):
...: foo = FooDec()
...:

In [17]: class People(metaclass=Meta):
...: foo = FooDec()
...:

In [18]: People.foo
__get__ called with: instance: <class '__main__.People'>, owner: <class '__main__.Meta'>

In [19]: People.foo = 100
__set__ called with: instance: <class '__main__.People'>, value: 100

In [20]: p = People()

In [21]: p.foo
__get__ called with: instance: <__main__.People object at 0x7faa0b2cb1c0>, owner: <class '__main__.People'>

In [22]: p.foo = 1
__set__ called with: instance: <__main__.People object at 0x7faa0b2cb1c0>, value: 1

关于python - 使用类名在Python中设置描述符属性的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58779199/

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