Python中的对象树

时间:2015-09-16 11:08:06

标签: python oop

我想在字典或类似对象上进行自动完成以访问对象。这就是我目前所拥有的:

class Foo:
   def DoFoo(self):
      pass

list = {"x": Foo(), "y": Foo()}

现在我希望能够做到:

list.x.DoFoo()

如何使用以后可以通过IPython自动完成访问的对象填充列表?

我看到here时是否需要某种“班级工厂”?

2 个答案:

答案 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

More to read

答案 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