简体   繁体   English

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

[英]What is __methods__ and why is it calling __getattr__?

I have recently tried to implement a "pass through" on my a few classes to allow calling methods on specific properties of a classes using the __getattr__ method. 我最近尝试在我的几个类上实现“传递”,以允许使用__getattr__方法调用类的特定属性上的方法。 This has broken (sort-of) autocompleting in ipython and I am curious to understand why. 这已经在ipython中破坏了(类型)自动完成,我很想知道为什么。 First: 第一:

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)

When creating an instance of this class and then attempting to tab-complete in Ipython (0.12.1), it seems that several functions are called including __methods__ , trait_names and _getAttributeNames . 在创建此类的实例然后尝试在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

I am curious to understand what is happening. 我很想知道发生了什么。

Thanks, 谢谢,

PS I know that doing this is very opaque and is temporary. PS我知道这样做是非常不透明的,而且是暂时的。 Still, I'm curious. 不过,我很好奇。

UPDATE UPDATE

Based on what I learned from the accepted answer below I have been able to successfully "pass through" autocompletion so that methods that exist in ClassProperty now autocomplete on instances of MyClass . 基于我从下面接受的答案中学到的东西,我已经能够成功“通过”自动完成,以便ClassProperty中存在的方法现在可以在MyClass实例上自动完成。 What was required to successfully pass through was an update to the __dir__ method 成功通过所需的是对__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

The reason why I have implemented this is because we are using python as an instrument control package with an ipython command line interface. 之所以我实现这个,是因为我们使用python作为带有ipython命令行界面的仪器控制包。 We have devices (ie a laser) that selects an actuator based on json config file. 我们有基于json配置文件选择执行器的设备(即激光器)。 We want to have top level access to the methods on the actuator for user convenience. 为了方便用户,我们希望能够对执行器上的方法进行顶级访问。

I would be curious if there are thoughts on my approach and if I am inviting any problems down the road. 如果有关于我的方法的想法,以及我是否在接受任何问题,我会很好奇。

IPython is asking your object for a list of its attributes, trying several protocols of varying levels of obscurity. IPython正在向你的对象询问其属性列表,尝试了几种不同程度的默默无闻的协议。 None of these protocols are part of the core Python language (at least, not any more), and the current IPython source code seems to have removed most of these checks. 这些协议都不是核心Python语言的一部分(至少,不再是),而且当前的IPython源代码似乎已经删除了大部分这些检查。


__methods__ is a really old part of Python that was phased out when they unified the type and class systems way back in 2.2, about 14 years ago. __methods__是Python的一个非常古老的部分,当它们在大约14年前的2.2中统一类型和类系统时被逐步淘汰。

It used to be the case that instances of built-in types would provide a __methods__ attribute that would be a list of all the methods they supported. 过去,内置类型的实例将提供__methods__属性,该属性将是它们支持的所有方法的列表。 This required an instance of the type, and the system it was part of had a number of other flaws. 这需要一个类型的实例,它所属的系统有许多其他缺陷。

In contrast, user-defined classes provided the introspection system you're familiar with from modern Python, with object and class __dict__ s. 相比之下,用户定义的类提供了您熟悉现代Python的内省系统,具有对象和类__dict__ This was more powerful and more consistent than the other system, so when they unified types and classes, the class-based introspection system was kept and the other was removed. 这比其他系统更强大,更一致,因此当它们统一类型和类时,基于类的内省系统被保留,另一个被删除。

__methods__ is pretty much completely gone now. __methods__现在已经完全消失了。 There might be some third-party legacy code still providing a __methods__ attribute, but the only thing that comes with Python that still supports __methods__ seems to be this weird thing in idlelib . 可能有一些第三方遗留代码仍然提供__methods__属性,但是仍然支持__methods__ Python附带的唯一东西似乎是在idlelib中这个奇怪的东西 In Python 2, dir still tries to look for it , though, and IPython's tab completion uses dir , so that's where the __methods__ access is coming from. 在Python 2中, dir仍然试图寻找它 ,而且IPython的tab完成使用dir ,所以这就是__methods__访问的来源。 There should also be an attempt to access __members__ , which you might not have noticed due to the message appearing on the same line you were typing on. 还应该尝试访问__members__ ,由于该消息出现在您输入的同一行上,您可能没有注意到__members__


_getAttributeNames is a protocol apparently introduced by PyCrust, an alternative Python shell. _getAttributeNames是一个显然由PyCrust引入的协议,PyCrust是一个替代的Python shell。 If defined, a _getAttributeNames method would provide a list of all dynamic attributes an object supports through __getattr__ . 如果已定义, _getAttributeNames方法将通过__getattr__提供对象支持的所有动态属性的列表。 (This was before __getattribute__ existed.) (这是在__getattribute__存在之前。)

_getAttributeNames appears to have been introduced around 2001 , making it newer than __methods__ , which disappeared around the same time frame. _getAttributeNames似乎是在2001年左右推出的 ,它比__methods__更新,它在同一时间框架内消失了。 Some time since IPython 0.12.1, the _getAttributeNames check has been removed from IPython . 自IPython 0.12.1以来的一段时间, _getAttributeNames检查已从IPython中删除


trait_names comes from Enthought Traits . 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. 对于使用traits的类, trait_names方法是一个实例方法,它返回其特征名称的列表。 It also accepts search criteria to list specific traits. 它还接受搜索条件以列出特定特征。 Like _getAttributeNames , this has been removed from IPython , apparently because the check isn't needed to handle traits (any more?). 就像_getAttributeNames一样, 这已经从IPython中删除了 ,显然是因为不需要检查来处理特征(更多?)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM