【问题标题】:Avoid Pycharm __dict__ lookup when using __getattr__ and __slots__ for composition使用 __getattr__ 和 __slots__ 进行组合时避免 Pycharm __dict__ 查找
【发布时间】:2021-01-04 07:15:15
【问题描述】:

假设我有一堂课:

class Example:
    __slots__ = ("_attrs", "other_value")
    
    def __init__(self):
       self._attrs = OrderedDict()
       self.other_value = 1
       self.attribute = 0
    
    def __setattr__(self, key, value):
       if key in self.__slots__:
            return super().__setattr__(key, value)
       else:
           self._attrs[key] = value
     
    def __getattr__(self, key):
         return self._attrs[key]

目标是让 Example 有两个插槽:

  • 如果已设置,则照常设置。 (作品)
  • 如果设置了其他属性,请在 _attrs 中分配它们。 (作品)

为了获取属性,代码应该:

  • 如果请求来自 slots 的任何内容,请照常行事(有效)
  • 如果 _attrs.keys() 中存在,则从 _attrs 获取值(有效)
  • 在任何其他情况下照常出错(问题)。

对于这个问题,我希望该错误能够模拟如果对象不存在属性时通常会发生的情况。目前在运行代码时,我在 self._attrs 上遇到一个关键错误。虽然这很好,但最好能隐藏这种细微差别。更烦人的是,如果我在 Pycharm 中调试,自动完成功能会在我按下回车键之前尝试查看 dict 时抛出一个大错误:

Example().abc # hit tab in pycharm

# returns the error:
Traceback (most recent call last):
  File "/Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py", line 1464, in do_it
    def do_it(self, dbg):
  File "/Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/_pydev_bundle/_pydev_completer.py", line 159, in generate_completions_as_xml
    def generate_completions_as_xml(frame, act_tok):
  File "/Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/_pydev_bundle/_pydev_completer.py", line 77, in complete
    def complete(self, text):
  File "/Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/_pydev_bundle/_pydev_completer.py", line 119, in attr_matches
    def attr_matches(self, text):
  File "/Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/_pydev_bundle/_pydev_imports_tipper.py", line 165, in generate_imports_tip_for_module
    def generate_imports_tip_for_module(obj_to_complete, dir_comps=None, getattr=getattr, filter=lambda name:True):
  File "/Users/xxxxxxxxx/", line 46, in __getattr__
    def __getattr__(self, key: str) -> None:
KeyError: '__dict__'

有没有办法通过不同的代码编写来抑制这种情况?

【问题讨论】:

  • woops - 在尝试提供最小可重复性示例时错过了这一点,我现在已经对其进行了修改

标签: python-3.x pycharm getattr slots


【解决方案1】:

您也许可以通过实现__dir__ on the class, so it has a canonical source of names that can be completed 使其工作:

def __dir__(self):
    return 'other_value', *self._attrs.keys()

我不能发誓 PyCharm 是如何实现它们的 tab-completion 的,所以不能保证它可以工作,但这是为一个类型定义一组可枚举属性的方法,希望 PyCharm 在可用时使用它,而不是而不是去__dict__

另一种方法(无论如何这可能是一个好主意)它确保在__getattr__ 失败时引发正确的错误,因此 PyCharm 知道问题是缺少属性,而不是与dict 无关的问题:

def __getattr__(self, key):
    try:
        return self._attrs[key]
    except KeyError:
        raise AttributeError(key)

【讨论】:

  • 为建议喝彩,遗憾的是重写 dir 并没有解决问题。很好的调用来引发属性错误!
  • @AlesiRowland:提高AttributeError 是否解决了 PyCharm 的问题?
  • 刚刚检查过,确实做到了!再次感谢
猜你喜欢
  • 2012-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-27
  • 2020-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多