You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中__dict__与实例属性触发__getattribute__的差异及疑问

Python属性访问与赋值的实验分析

实验验证与现象

1. 验证self.__dict__会触发__getattribute__

class Room:
    def __init__(self,name):
        self.name = name
    def __getattribute__(self,attr):
        print('in __getattribute__',attr)
        return  object.__getattribute__(self,attr)
    def __setattr__(self,attr,value):
        print('in __setattr__',attr)
        self.__dict__[attr] = value
        print('over')

实例化输出(含注释):

x = Room('r1')
# __init__中的self.name = name触发__setattr__
in __setattr__ name  
# Python解释器解析self.__dict__[attr] = value时,提取self.__dict__触发__getattribute__
in __getattribute__ __dict__  
over

可见解释器在解析代码片段时,部分操作会触发__getattribute__。

2. 描述符调用的特殊现象

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.name会触发__get__方法,但执行p.name = 'tom'时仅触发__set__方法,疑问:为何赋值操作不先提取p.name触发__get__再执行赋值?

3. 反驳“默认__setattr__通过原生内部槽操作,不经过__getattribute__”的观点

针对该观点设计实验如下:

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

实例化时会触发无限递归,由此可见self.__setattr__会触发__getattribute__。

初步结论

  • 不触发__getattribute__的表达式:
super().__setattr__(attr, value)  
object.__setattr__(self,attr, value)
  • 触发__getattribute__的表达式:
self.__setattr__(attr, value)
self.__dict__[attr] = value

待解谜题

  1. 为何结构相似的三个表达式中,仅self.__setattr__(attr, value)会触发__getattribute__?
  2. 同为赋值语句,self.__dict__[attr] = value会触发__getattribute__,为何self.name = name不会?
  3. 在property中,self.__setattr__('name', value)为何触发set方法而非__getattribute__?实验代码如下:
import time
class Room:
     def __init__(self,value):
         self.name = value  
     def get_name(self):
         print('in get')
         return self.__dict__['name']       
     def set_name(self, value):
         print('in set')
         time.sleep(3)
         self.__setattr__('name', value)
     name = property(get_name, set_name) 
r = Room('r1')

内容的提问来源于stack exchange,提问作者showkey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 03:20:57