代码之家  ›  专栏  ›  技术社区  ›  alfonsoSR

抑制AttributeError上的建议-Python 3.12

  •  1
  • alfonsoSR  · 技术社区  · 1 年前

    我喜欢使用 __getattr__ 为对象提供可选属性,同时避免出现问题 None 。这是一个简单的例子:

    from typing import Any
    
    class CelestialBody:
    
        def __init__(self, name: str, mass: float | None = None) -> None:
    
            self.name = name
            self._mass = mass
    
            return None
    
        def __getattr__(self, name: str) -> Any:
    
            if f"_{name}" not in self.__dict__:
                raise AttributeError(f"Attribute {name} not found")
    
            out = getattr(self, f"_{name}")
            if out is None:
                raise AttributeError(f"Attribute {name} not set for {self.name}")
            return out
    

    我的问题是,当我提出我的自定义时,Python试图表现得很好 AttributeError 并公开我正在为其创建接口的“私有”属性:

    AttributeError: Attribute mass not set for Earth. Did you mean: '_mass'?
    

    有没有标准的方法来抑制这些建议?

    1 回复  |  直到 1 年前
        1
  •  2
  •   jonrsharpe    1 年前

    名称推荐逻辑为 triggered 只有当 name 的属性 AttributeError 不是 None :

    elif exc_type and issubclass(exc_type, (NameError, AttributeError)) and \
            getattr(exc_value, "name", None) is not None:
        wrong_name = getattr(exc_value, "name", None)
        suggestion = _compute_suggestion_error(exc_value, exc_traceback, wrong_name)
        if suggestion:
            self._str += f". Did you mean: '{suggestion}'?"
    

    因此,您可以通过设置轻松禁用该建议 名称 没有一个 当实例化 AttributeError :

    if out is None:
        raise AttributeError(f"Attribute {name} not set for {self.name}", name=None)
    

    Demo here

        2
  •  1
  •   jonrsharpe    1 年前

    这是一个已知的问题: python/cpython#116871 。它将在Python 3.13*中通过 python/cpython#116930 ,为添加了一个功能 hide_underscored 的处理 AttributeError 建议:

        if isinstance(exc_value, AttributeError):
            obj = exc_value.obj
            try:
                d = dir(obj)
                hide_underscored = (wrong_name[:1] != '_')
                if hide_underscored and tb is not None:
                    while tb.tb_next is not None:
                        tb = tb.tb_next
                    frame = tb.tb_frame
                    if 'self' in frame.f_locals and frame.f_locals['self'] is obj:
                        hide_underscored = False
                if hide_underscored:
                    d = [x for x in d if x[:1] != '_']
            except Exception:
                return None
    

    所以,如果你试图找到“错误的名字”( "mass" )本身不是以下划线开头,并且您没有访问上的属性 self ,任何名称 从一开始将被排除在回溯建议之外。据我所知,在此期间无法完全禁用这些功能。


    * this commit 标记为3.13.0b1,尽管该功能的描述尚未(?)添加到 What’s New In Python 3.13 .