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

Python:如何安全查找属性且不触发类或元类的__getattribute__?

如何安全查找属性,不触发类或元类的__getattribute__方法?

需要一种无需try-catch的100%安全方式,用于查找Python对象或类型的属性,要求完全不触发类或元类的__getattribute__方法。原本认为object.__getattribute__是安全的,但实际调用时抛出了AttributeError,报错信息如下:

Traceback (most recent call last):
  File "C:\GitHub\PyKotor\Libraries\Utility\src\utility\tricks.py", line 49, in update_class_instances
    if isinstance(obj, old_class):
  File "C:\GitHub\PyKotor\Libraries\Utility\src\utility\system\path.py", line 104, in __instancecheck__
    return cls.__subclasscheck__(instance.__class__)
  File "C:\GitHub\PyKotor\Libraries\Utility\src\utility\system\path.py", line 107, in __subclasscheck__
    return pathlib_to_override(cls) in pathlib_to_override(subclass).__mro__
  File "C:\GitHub\PyKotor\Libraries\Utility\src\utility\logger_util.py", line 471, in __getattribute__
    return getattr(instance, attr_name)
  File "C:\GitHub\PyKotor\Libraries\Utility\src\utility\logger_util.py", line 524, in __getattribute__
    if isinstance(e, AttributeError) and object.__getattribute__(self, "__getattr__") is not None:
AttributeError: 'ExampleClass' object has no attribute '__getattr__'

随后尝试type.__getattribute__也出现类似错误:

Traceback (most recent call last):
  File "C:\GitHub\PyKotor\Libraries\Utility\src\utility\tricks.py", line 83, in debug_reload_pymodules
    update_class_instances(old_attribute, new_attribute)
  File "C:\GitHub\PyKotor\Libraries\Utility\src\utility\tricks.py", line 52, in update_class_instances
    RobustRootLogger.exception(f"Error updating class '{old_class.__class__.__name__}'")
  File "C:\GitHub\PyKotor\Libraries\Utility\src\utility\logger_util.py", line 471, in __getattribute__
    return getattr(instance, attr_name)
  File "C:\GitHub\PyKotor\Libraries\Utility\src\utility\logger_util.py", line 524, in __getattribute__
    if isinstance(e, AttributeError) and type.__getattribute__(our_type, "__getattr__") is not None:
AttributeError: type object 'ExampleClass' has no attribute '__getattr__'

注:当前正在研究Python内部机制,涉及importlib、__import__和sys.modules。


安全属性查找方案

要完全绕过自定义__getattribute__的拦截,需直接操作对象的底层属性存储(字典),避免触发任何自定义属性访问逻辑。以下是实现思路:

  1. 实例属性查找:

    • 通过object.__getattribute__(obj, '__dict__')获取实例自身的属性字典(此调用仅触发object基类的原生逻辑,不会触发子类自定义的__getattribute__)。
    • 若实例因使用__slots__没有__dict__,则直接遍历其类的MRO链查找属性。
  2. 类属性查找:

    • 遍历类的MRO(方法解析顺序)链,依次检查每个基类的__dict__字典。

以下是无需调用方额外加try-catch的实现(内部少量try-catch用于处理无__dict__的情况):

def safe_getattr(obj, attr_name, default=None):
    # 处理实例对象
    if not isinstance(obj, type):
        # 尝试获取实例自身的属性字典
        try:
            obj_dict = object.__getattribute__(obj, '__dict__')
            if attr_name in obj_dict:
                return obj_dict[attr_name]
        except AttributeError:
            # 实例无__dict__(如使用__slots__),跳过直接查类
            pass
        # 获取实例所属的类
        cls = type(obj)
    else:
        # 处理类/元类对象
        cls = obj
    
    # 遍历类的MRO链查找属性
    for base in cls.__mro__:
        base_dict = object.__getattribute__(base, '__dict__')
        if attr_name in base_dict:
            return base_dict[attr_name]
    
    # 找不到属性返回默认值
    return default

说明

  • 此方法完全绕过自定义的__getattribute__,仅依赖Python原生逻辑获取属性字典,不会触发任何自定义逻辑。
  • 属性不存在时直接返回指定默认值,无需调用方处理异常。
  • 支持实例、类、元类等所有Python对象的属性查找。

内容的提问来源于stack exchange,提问作者Benjamin Auquite Wizard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 04:17:18