【问题标题】:IPython auto completion is calling __getattr__IPython 自动完成正在调用 __getattr__
【发布时间】:2020-05-04 16:31:04
【问题描述】:

感谢您花时间阅读本文。希望在这些奇怪的时刻你一切都好。

我正在实现一个类并开始研究如何为其属性提供自动完成功能。 根据我的在线研究,我得出结论,ipython 完成来自__dir__ 方法。

__getattr__ 通常在您访问不存在的属性时被调用。在我的项目中,如果发生这种情况,则会运行需要一段时间的操作。为什么 ipython 试图访问属性而不是仅仅显示 __dir__ 返回的内容?

在单元格 2 中,我在点后点击选项卡以要求完成。

【问题讨论】:

  • 这不是 iPython 特有的; __getattr__ 似乎是在 __dir__ 返回的列表的最后一项上调用的,即使在 CPython 中也是如此。
  • 刚刚检查过,__dir__ 的每个元素都会调用它
  • 我不确定。您可能想深入了解rlcompleter module,CPython(可能还有 iPython)使用它来启用制表符补全。模块 cmets 明确提到了 __getattr__ 被调用的风险,尽管对我来说如何发生这种情况并不明显。
  • 真的很奇怪。我会调查此事。

标签: python python-3.x jupyter-notebook ipython


【解决方案1】:

我认为问题在于您需要一个类的实例。这些方法是实例方法。

我添加了日志记录以便于调试。当我example.somethingexample.<tab> 时,我在ipython 控制台中得到输出。

  • Python 3.8.2 版
  • IPython 版本 7.14.0

这是我的观察:<tab> __dir__ 被调用,返回的项目集合显示在 IPython 控制台中。如果在<tab> 之后选择的项不是对象的属性,则调用__getattr__ 以尝试查找它。

import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)


class Example:
    def __init__(self):
        logging.info("init")
        self._attrs = ("foo", "bar", "baz")
        for attr in self._attrs:
            setattr(self, attr, attr)

    def __getattr__(self, attr):
        logging.info(f"__getattr__ called: {attr}")

    def __dir__(self):
        logging.info("__dir__ called")
        return ("extra", *self._attrs)


# Create an instance of Example.
# The instance methods can then be called on the instance.
example = Example()

if __name__ == "__main__":
    logging.info(example)

【讨论】:

  • 我的错,我忘了创建对象。我已经编辑过了。我使用了睡眠,因为 ipython 调用该方法时不会显示打印。这就是为什么在您的代码中问题似乎消失了。如果你添加一个睡眠,你可以看到自动完成正在调用__getattr__
  • 如果它解决了您的问题,请接受答案。谢谢你。我可以发誓我看到了print 的一些输出。现在我不是了。
  • 它没有解决问题。就像我说的,如果您将睡眠添加到代码中并尝试自动完成,则需要 2 秒。我的问题是自动完成调用 getattr。我忘记在我的示例中实例化对象,但这不是我的问题。
  • 你期望__getattr__在tab键被按下时被调用吗?根据我的观察,当按下 Tab 键时会调用 __dir__ 方法。
  • 正在调用__dir__,这就是我所期望的。我没有得到什么,我提出的问题是__getattr__ 在不应该被调用的时候也被调用了。您可以通过添加睡眠来验证它。当你点击选项卡时,它会调用 dir (我想要的),但它会调用 getattr,只有在你访问属性时才应该调用它。并且自动完成不应该访问该属性。那是写在我的问题中的。请检查问题。
【解决方案2】:

所以我想出了一个解决方法。如果您知道需要很长时间的属性名称,则仅在传递该属性名称时执行自定义 getattr 代码,否则只会引发属性错误。这对我有用。

【讨论】:

    猜你喜欢
    • 2014-02-23
    • 1970-01-01
    • 1970-01-01
    • 2016-04-15
    • 2017-04-27
    • 1970-01-01
    • 2017-03-25
    • 2015-05-27
    • 2013-04-14
    相关资源
    最近更新 更多