我想在字典或类似对象上进行自动完成以访问对象。这就是我目前所拥有的:
class Foo:
def DoFoo(self):
pass
list = {"x": Foo(), "y": Foo()}
现在我希望能够做到:
list.x.DoFoo()
如何使用以后可以通过IPython自动完成访问的对象填充列表?
我看到here时是否需要某种“班级工厂”?
答案 0 :(得分:1)
您需要覆盖__getattr__
:
class Foo(object):
attr_a = 'default_attr_a_value'
attr_b = 'default_attr_b_value'
def __init__(self, *args, **kwargs):
if len(args) >= 2:
self.attr_a = args[0]
self.attr_b = args[1]
if len(args) == 1:
self.attr_a = args[0]
# holds the "emulated" attributes
self._properties = kwargs
def __getattr__(self, name):
if name in self._properties:
return self._properties[name]
else:
raise AttributeError
def __hasattr__(self, name):
return name in self._properties
bar = Foo('modified_value_of_attr_a', **{'aaa':1,'bbb':2})
print bar.attr_a
print bar.attr_b
print bar.aaa
try:
print bar.sss
except AttributeError:
print 'Attribute error raised!'
list_attrs = ['attr_a', 'aaa', 'sss']
for a in list_attrs:
if hasattr(bar, a):
print 'bar, instance of Foo, has an attribute named "%s"' % a
else:
print 'bar, instance of Foo, doesn\'t have an attribute named "%s"' % a
答案 1 :(得分:1)
自定义类的实例可以作为您在其上设置的属性的容器。这可以简单地开始:
class MyContainer:
pass
a = MyContainer()
a.x = Foo()
a.y = Foo()
a.x.DoFoo()
你可以让它变得更复杂,能够传递你想要的属性作为构造函数的一部分(使用与dict
构造函数相同的语义):
def MyContainer:
def __init__(self, vals={}, **kwvals):
self.__dict__.update(vals, **kwvals)
a = MyContainer({"x":Foo()}, y=Foo()) # there are multiple ways to pass the args
a.x.DoFoo()
如果在创建此类容器后不需要添加或删除值,则可以使用标准库的collections.namedtuple
类工厂。您传递一个类名和一系列属性名称,它将返回一个新类。
from collections import namedtuple
A = namedtuple("A", ["x", "y"])
a = A(Foo(), y=Foo()) # can use positional or keyword arguments
a.x.DoFoo() # this still works!
a.x = "something else" # but this will raise an error