何时以及为什么应该使用命名元组而不是字典?

241

标准库中的namedtuple类似乎是将元组变得更像字典的一种方式。那么namedtupledict相比如何?什么时候应该使用它们?它们是否适用于非可哈希类型?


2
看一下这个问题 - https://dev59.com/53A85IYBdhLWcg3wCe9Z - ronakg
6
请参考2970608中的命名元组FAQ,其中有一个问题是与字典进行比较。 - Tom Hundt
2个回答

275
在字典中,只有键需要是可哈希的,而不是值。而`namedtuple`没有键,因此可哈希性不是问题。然而,它们有一个更严格的限制 - 它们的键等效项,即“字段名称”,必须是字符串。基本上,如果你要创建一个类的多个实例,例如:
class Container:
    def __init__(self, name, date, foo, bar):
        self.name = name
        self.date = date
        self.foo = foo
        self.bar = bar

mycontainer = Container(name, date, foo, bar)

如果您希望__init__中设置属性后不更改它们的值,可以使用以下方法:

Container = namedtuple('Container', ['name', 'date', 'foo', 'bar'])

mycontainer = Container(name, date, foo, bar)
当然,你可以创建一堆包含相同键的字典,但假设你只会使用有效的Python标识符作为键且不需要可变性,as a replacement.
mynamedtuple.fieldname
比起原来,

更漂亮

mydict['fieldname']
并且
mynamedtuple = MyNamedTuple(firstvalue, secondvalue)
比起…更漂亮
mydict = {'fieldname': firstvalue, 'secondfield': secondvalue}

最后,namedtuple是有序的,与常规的dict不同,因此您会按照定义字段的顺序获取项目,而不是dict


45
引用 Raymondh 的话:“命名元组(named tuples)的实例使用的空间不比普通元组多。字段名称属性存储在命名元组类中。” https://twitter.com/raymondh/status/524660721968107521 - Moberg
8
还有一件需要注意的事情是,命名元组也可以被初始化为 mynamedtuple = MyNamedTuple(fieldname=firstvalue, secondfield=secondvalue) - Bharat Khatri
2
你可以使用Container = namedtuple('Container', 'name date foo bar')来使实例化更加简洁漂亮。 - stackPusher
19
如果您正在使用Python 3.7或CPython 3.6,那么dicts是有顺序的,即按照插入顺序排序。 - user3064538
1
@Boris 很好的信息,但仍然与字段定义排序不同,在许多情况下就像随机排序一样未知。 - agf
显示剩余2条评论

49

元组是不可变的,无论是否命名。使用 namedtuple 只是通过使用名称而不是索引使访问更加方便。您只能为 namedtuple 使用有效的标识符,它不执行任何哈希操作,而是生成一个新类型。


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