什么是__methods__,为什么调用__getattr __?

时间:2015-12-17 00:37:01

标签: python ipython magic-methods

我最近试图实现"传递"在我的几个类上允许使用__getattr__方法调用类的特定属性上的方法。这已经在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)

在创建此类的实例然后尝试在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。我知道这样做是非常不透明的,而且是暂时的。不过,我很好奇。

更新

根据我从下面接受的答案中学到的东西,我已经能够成功地通过&#34;自动完成,以便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配置文件选择执行器的设备(即激光器)。为了方便用户,我们希望能够对执行器上的方法进行顶级访问。

如果有关于我的方法的想法以及我是否在接受任何问题,我会很好奇。

1 个答案:

答案 0 :(得分:5)

IPython正在向你的对象询问其属性列表,尝试了几种不同程度的默默无闻的协议。这些协议都不是核心Python语言的一部分(至少,不再是),而且当前的IPython源代码似乎已经删除了大部分这些检查。

__methods__ 是Python的一个非常古老的部分,它们在大约14年前以unified the type and class systems的方式逐渐退出。

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

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

__methods__现在已经完全消失了。可能有一些第三方遗留代码仍然提供__methods__属性,但Python仍然支持__methods__的唯一内容似乎是this weird thing in idlelib。但是,在Python 2中,dir still tries to look for it和IPython的选项卡完成使用dir,因此__methods__访问权来自何处。还应该尝试访问__members__,由于该消息出现在您输入的同一行上,您可能没有注意到这一点。

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

_getAttributeNames appears to have been introduced around 2001,使其比__methods__更新,它在同一时间范围内消失。自IPython 0.12.1起的一段时间,_getAttributeNames check has been removed from IPython

trait_names 来自Enthought Traits。对于使用traits的类,trait_names method是一个返回其traits名称列表的实例方法。它还接受搜索条件以列出特定特征。与_getAttributeNamesthis has been removed from IPython一样,显然是因为不需要检查来处理特征(更多?)。