__methods__ 是什么,为什么调用 __getattr__?

What is __methods__ and why is it calling __getattr__?

我最近尝试在我的几个 classes 上实现 "pass through" 以允许使用 __getattr__ 方法调用 classes 的特定属性的方法.这破坏了 ipython 中的(某种)自动完成功能,我很想知道为什么。 第一:

class MyClass(object):
    def __init__():
        #create an instance of class ClassProperty
        self.class_property = ClassProperty()

    def __getattr__(self, item):
        #pass through calls to non-existent methods, print first
        print item
        return getattr(self.class_property,item)

当创建此 class 的实例然后尝试在 Ipython (0.12.1) 中完成制表符时,似乎调用了几个函数,包括 __methods__trait_names_getAttributeNames.

In [1]: my_class = MyClass()
In [2]: my_class.not_in_my_class<tab>
__methods__
trait_names
_getAttributeNames

我很想知道发生了什么。

谢谢,

P.S。我知道这样做是非常不透明的,而且是暂时的。不过,我很好奇。

更新

根据我从下面接受的答案中学到的知识,我已经能够成功 "pass through" 自动完成,因此 ClassProperty 中存在的方法现在可以在 MyClass 的实例上自动完成。成功通过所需的是更新 __dir__ 方法

class MyClass(object):
    def __init__():
        #create an instance of class ClassProperty
        self.class_property = ClassProperty()

    def __getattr__(self, item):
        #pass through calls to non-existent methods, print first
        print item
        return getattr(self.class_property,item)

    def __dir__(self):
        dir_list = self.__dict__.keys()
        try:
            dir_list.extend(dir(self.class_property))
        except:
            pass
        return dir_list

我实现这个的原因是因为我们使用 python 作为带有 ipython 命令行界面的仪器控制包。我们有设备(即激光器)根据 json 配置文件选择执行器。为了方便用户,我们希望对执行器上的方法进行顶级访问。

我很好奇是否有人对我的方法有任何想法,以及我是否会在未来引发任何问题。

IPython 正在向您的对象询问其属性列表,并尝试了几种不同级别的模糊协议。 None 这些协议是核心 Python 语言的一部分(至少,不再是),当前的 IPython 源代码似乎已经删除了大部分这些检查。


__methods__ 是 Python 的一个非常古老的部分,当他们 unified the type and class systems 回到 2.2 时就被淘汰了,大约 14 年以前。

过去,内置类型的实例会提供一个 __methods__ 属性,该属性将是它们支持的所有方法的列表。这需要一个类型的实例,而它所属的系统有许多其他缺陷。

相比之下,用户定义的 classes 提供了您熟悉的现代 Python 内省系统,其中包含对象和 class __dict__s。这比其他系统更强大、更一致,所以当他们统一类型和 classes 时,基于 class 的内省系统被保留,另一个被删除。

__methods__ 现在几乎完全消失了。可能有一些第三方遗留代码仍然提供 __methods__ 属性,但是 Python 附带的唯一仍然支持 __methods__ 的东西似乎是 this weird thing in idlelib. In Python 2, dir still tries to look for it,不过, IPython 的制表符完成使用 dir,因此这就是 __methods__ 访问的来源。还应该尝试访问 __members__,由于消息出现在您键入的同一行上,您可能没有注意到。


_getAttributeNames 显然是由 PyCrust 引入的协议,替代 Python shell。如果已定义,_getAttributeNames 方法将提供对象通过 __getattr__ 支持的所有动态属性的列表。 (这是在 __getattribute__ 存在之前。)

_getAttributeNames appears to have been introduced around 2001, making it newer than __methods__, which disappeared around the same time frame. Some time since IPython 0.12.1, the _getAttributeNames check has been removed from IPython.


trait_names 来自 Enthought Traits. For a class that uses traits, the trait_names method is an instance method that returns a list of the names of its traits. It also accepts search criteria to list specific traits. Like _getAttributeNames, this has been removed from IPython,显然是因为不需要检查来处理特征(不再?)。