在命名元组中设置可选变量

8
from collections import namedtuple

FooT = namedtuple('Foo', 'foo bar')
def Foo(foo=None, bar=None):
  return FooT(foo,bar)

foo = Foo()
foo.foo = 29
throws attribute error

所以,我的使用情况是一个数据结构,它有可选字段..但如果需要的话应该能够修改它。


因为元组是不可变的,所以一旦创建后就无法修改它们。 - Lev Levitsky
正如enrico在下面指出的,不可变并不意味着您永远不需要更改数据:可以使用_replace()来更新值并返回一个新的不可变结构。请查看typing.NamedTuple,自3.6.1起,它支持默认值。 - thom_nic
5个回答

5

元组在定义时是不可变的。命名元组也遵循这个模式。

在Python3中,似乎有一个名为SimpleNamespace[1]的东西可以使用。但如果你想要使用一个简单的读写数据结构,你可以创建一个类并对其成员设置限制。

[1] - 为什么Python不支持记录类型,即可变的命名元组


5
一个 defaultdict 应该符合您的需求。它在构建时提供一个函数,每次访问未设置的元素时都会调用它。以下是示例演示:
>>> from collections import defaultdict
>>> d = defaultdict(lambda:None)
>>> d['foo'] = 10
>>> d['bar'] = 5
>>> print d['baz']
None
>>> d['baz'] = 15
>>> print d['baz']
15

2

命名元组(namedtuple)和元组一样不可修改。由于问题涉及到命名元组,有时候使用_replace方法创建一个新对象是可以接受的(甚至更好)。当然,对同一对象的其他引用将保持不变。

from collections import namedtuple

FooT = namedtuple('Foo', 'foo bar')
def Foo(foo=None, bar=None):
  return FooT(foo,bar)

foo = Foo()
foo = foo._replace(foo=29)

2
针对以上答案的轻微变化,为什么不扩展tutorial中的建议并创建一个类,在未定义属性时返回None?例如:
class Foo(object):
    def __getattr__(self, name):
        return None

这与defaultdict非常相似,但可以通过直接属性访问,就像命名元组一样。

0
为什么不直接使用类呢?
class Foo(object):

   def __init__(foo=None, bar=None):
     self.foo = foo
     self.bar = bar

foo = Foo()
foo.foo = 29

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接