使用 __getattr__ 和 __slots__ 进行组合时避免 Pycharm __dict__ 查找
Avoid Pycharm __dict__ lookup when using __getattr__ and __slots__ for composition
假设我有一个 class:
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]
目标是让示例有两个插槽:
- 如果已设置,则照常设置。 (作品)
- 如果设置了附加属性,请在 _attrs 中分配它们。 (作品)
要获取属性,代码应该:
- 如果请求 slots 中的任何内容,则照常进行(有效)
- 如果 _attrs 存在于 _attrs.keys() 中,则从中获取值(有效)
- 在任何其他情况下都会像往常一样出错(问题)。
对于这个问题,我希望错误能够模拟如果对象的属性不存在时通常会发生的情况。当前,当 运行 代码时,我在 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__'
有没有办法通过编写不同的代码来抑制这种情况?
您可以通过实施 __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)
假设我有一个 class:
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]
目标是让示例有两个插槽:
- 如果已设置,则照常设置。 (作品)
- 如果设置了附加属性,请在 _attrs 中分配它们。 (作品)
要获取属性,代码应该:
- 如果请求 slots 中的任何内容,则照常进行(有效)
- 如果 _attrs 存在于 _attrs.keys() 中,则从中获取值(有效)
- 在任何其他情况下都会像往常一样出错(问题)。
对于这个问题,我希望错误能够模拟如果对象的属性不存在时通常会发生的情况。当前,当 运行 代码时,我在 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__'
有没有办法通过编写不同的代码来抑制这种情况?
您可以通过实施 __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)