当前位置: 首页 > 知识库问答 >
问题:

python3.x - 如何总结get,set调用的规则或者逻辑?

戴化
2023-08-06

p.attr = value
这个表达式,python解释器将从整体上,将它理解成一个赋值,触发set;而不会这样做,p.attr触发get,get代码执行完后,p.attr = value再触发set.

class Sample:    def __init__(self, name):        self.name = name    def __get__(self,instance,owner):        print('get called')    def __set__(self, instance, value):        print('set called')class Person:    name = Sample('name')

我们测试一下

p = Person()p.nameget calledp.name = 'tom'set called

好,我们来点其他的代码,观察一下python解释器

import timeclass Room:    def __init__(self,name):        self.name = name    def __getattribute__(self,key):        print('in __getattribute__',key)        return  object.__getattribute__(self,key)    def __setattr__(self,attr,value):        print('in __setattr__',attr)        time.sleep(3)        self.__setattr__(attr, value)        print('over')

初始化,看看发生什么

x = Room('r1')in __setattr__ namein __getattribute__ __setattr__in __setattr__ namein __getattribute__ __setattr__in __setattr__ namein __getattribute__ __setattr__in __setattr__ namein __getattribute__ __setattr__in __setattr__ namein __getattribute__ __setattr__in __setattr__ name

我试图解释一下,添加一点注释

x = Room('r1')in __setattr__ name                  #self.name = name 触发setattrin __getattribute__ __setattr__      #python读取self.__setattr__,触发getin __setattr__ name                  #get执行完成后,又进入了setin __getattribute__ __setattr__in __setattr__ namein __getattribute__ __setattr__in __setattr__ namein __getattribute__ __setattr__in __setattr__ namein __getattribute__ __setattr__in __setattr__ name

这句话
self.__setattr__(attr, value)
python解释器,读取了一部分self.__setattr__,触发get;get执行完成后,python解释器又从整体上self.__setattr__(attr, value),将它理解成set,进入set后,又碰上
self.__setattr__(attr, value)
于是不断循环,这个逻辑为何不作用到第一个例子?

python解释器读取p.name = 'tom'时,p.name触发get,然后整体上是一个set
为何不输出下面的结果:

p.name = 'tom'
get called
set called

请总结一下里面的规则。

共有1个答案

贝自怡
2023-08-06

考虑到自己曾经写的的笔记里没有这部分内容,所以特意查了下网络上已有的知识,先做个简要的总结在这里。
小注:在属性的读取和赋值过程中,Python解释器不会分别调用get和set方法。它会根据上述规则选择调用适当的方法来处理属性的读取和赋值操作。

属性的读取:

当我们使用instance.attr语法获取属性值时,Python解释器将按照以下顺序进行操作:
首先,它会检查是否定义了一个名为__getattribute__()的方法。如果定义了,则调用该方法。
如果未定义__getattribute__()方法,它会检查是否定义了一个名为__getattr__()的方法。如果定义了,则调用该方法。
如果以上两个方法都未定义,它会直接从实例的字典中获取属性的值。

属性的赋值:

当我们使用instance.attr = value语法给属性赋值时,Python解释器将按照以下顺序进行操作:
首先,它会检查是否定义了一个名为__setattr__()的方法。如果定义了,则调用该方法。
如果未定义__setattr__()方法,它会直接将属性添加到实例的字典中。

所以回过头看,在你提供的代码示例中,第一个例子中的Sample类是一个描述符类,它实现了描述符协议的__get__()和__set__()方法。这是一个特殊情况,当我们将一个描述符对象赋值给类的属性时,Python解释器会自动调用描述符的__get__()和__set__()方法来处理属性的读取和赋值。

而第二个例子中的Room类并不是一个描述符类,它定义了__getattribute__()和__setattr__()方法来自定义属性的读取和赋值操作。但是,在__setattr__()方法中,你使用了递归调用self.__setattr__(attr, value),导致了无限循环。这是因为在赋值过程中,每次调用__setattr__()方法都会再次触发__setattr__()方法,形成了无限递归。

 类似资料:
  • 定义一个简单的异常类: class myException(Exception): pass 定义一个函数 运行f1() Traceback (most recent call last): File "<stdin>", line 3, in f1 ZeroDivisionError: division by zero During handling of the above exception

  • 我的要求是,触发第二条规则,然后停止进程而不触发第三条规则

  • 我知道Drools中的“显着性”提供了对规则执行顺序的控制。但上面是一个例子,说明了当“显着性”不再能帮助我时所面临的问题。 在这里,我有三条规则正在相继执行: 我期望第三条规则被触发,并且控制台中有“规则被触发”行,但它没有被执行。 据我所知,问题在于规则评估阶段,当所有三个规则在执行前同时评估,然后才根据它们的“显着性”回合执行。 在评估的那一刻,$resource1.amount是5,这就是

  • 该页面翻译了官方的”Dart 语言简明教程“,其中多次提到 Dart 库教程、Dart 语言规范 和 高效的 Dart,译者有意在之后翻译”Dart 库教程“ 和 ”高效的 Dart“,其中 Dart 库教程 已翻译完成。请关注该代码仓库。

  • 我是ANTLR4的新手,我试图解析此输入 在这个输入中,A应该是一个函数调用,而B应该是一个名为B的变量。但我在lexer中有一个跳过空格的规则。 如何为此输入编写解析器规则,但保留跳过空格的规则 提前感谢