编码风格:轻量/最简单的方法来创建支持属性赋值的实例?

时间:2015-03-31 20:07:02

标签: python coding-style

我经常需要创建一个结果对象实例来从函数中返回复杂的值,并想知道什么是一个不错的Pythonic方法。

我知道密切相关的attribute-assignment-to-built-in-object,但它询问为什么他需要破解子类解决方法来使用' object'。我明白为什么。我问的是,标准库中是否存在现有支持以避免使用' object'和子类hack,通过现有的类或函数。

实例化支持属性赋值的实例的最轻,最Pythonic方法是什么?

我可以直接指向子类化' object'回答。这真的没什么大不了 - 只是想知道我是否错过了标准库或内置函数支持的更清晰的方法。

我想做的样本:

try:
    returnval = object()
    returnval.foo = 1
    returnval.bar = 2

    print "\n\nSuccess with %s" % (returnval), vars(returnval), "has __slots__:", hasattr(returnval, "__slots__"), "has __dict__:", hasattr(returnval, "__dict__")

except Exception, e:
    print "\n\nFailure with %s:%s" % (returnval, e), "has __slots__:", hasattr(returnval, "__slots__"), "has __dict__:", hasattr(returnval, "__dict__")

这正如预期的那样失败

Failure with <object object at 0x102c520a0>:'object' object has no attribute 'foo' has __slots__: False has __dict__: False

我并不感到惊讶。 &#39;对象&#39;是一个裸存根,并且不允许属性赋值,因为它没有__dict __。

相反,我必须声明一个占位符类。有更清洁的方式吗?

try:
    class Dummy(object): pass

    returnval = Dummy()
    returnval.foo = 1
    returnval.bar = 2
    print "\n\nSuccess with %s" % (returnval), vars(returnval), "has __slots__:", hasattr(returnval, "__slots__"), "has __dict__:", hasattr(returnval, "__dict__")

except Exception, e:
    print "\n\nFailure with %s:%s" % (returnval, e), "has __slots__:", hasattr(returnval, "__slots__"), "has __dict__:", hasattr(returnval, "__dict__")

这给出了:

Success with <__main__.Dummy object at 0x102d5f810> {'foo': 1, 'bar': 2} has __slots__: False has __dict__: True

使用Dummy / MyClass方法可以避免这些问题,但是它会给我的模块带来一些温和的代码气味,以便使用Dummy类。

不起作用/不满意的事情:

词典。如果我使用dict代替,我会避免这种情况,但我会失去简单的returnval.foo访问权限。

也许是AttrDict实现?但是那些是第三方软件包,而不是标准库。

嘲笑。不是我想在这里使用的,因为这不是测试代码,如果returnval.foo不存在,我想要抛出异常。

模块/类属性赋值。是的,我可以将属性分配给命名空间中的现有对象,如类或模块声明。但那时基本上就是将属性分配给单例,连续的函数调用会互相破坏。

2 个答案:

答案 0 :(得分:4)

使用namedtuple或坚持使用字典 - 如果您确实需要属性访问权限 - create your own class for it

>>> Dummy = namedtuple('Dummy', ['foo', 'bar'])
>>> d = Dummy(1, 2)
>>> d
Dummy(foo=1, bar=2)
>>> d.baz
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Dummy' object has no attribute 'baz'

答案 1 :(得分:1)

轻量级方法是使用函数作为容器

>>> foo = lambda: 0
>>> foo.bar = 'bar'
>>> foo.baz = 'baz'

如果要创建一堆具有相同属性的不可变对象collections.namedtuple可能更合适

>>> foo = namedtuple("foo", "bar, baz")
>>> Foo = foo('bar', 'baz')
>>> foo.bar
'bar'
>>> foo.baz
'baz'