我最近试图实现"传递"在我的几个类上允许使用__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配置文件选择执行器的设备(即激光器)。为了方便用户,我们希望能够对执行器上的方法进行顶级访问。
如果有关于我的方法的想法以及我是否在接受任何问题,我会很好奇。
答案 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名称列表的实例方法。它还接受搜索条件以列出特定特征。与_getAttributeNames
,this has been removed from IPython一样,显然是因为不需要检查来处理特征(更多?)。