namedtuple的第一个参数用于什么?

22

我们可以像这样使用namedtuple

>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p=Point(1,2)
>>> p.x
1

我发现namedtuple的第一个参数似乎是无用的,因为:

首先,我们不能使用它来创建实例,例如:

>>> from collections import namedtuple
>>> P = namedtuple('Point', ['x', 'y'])
>>> p = Point(1,2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'Point' is not defined

其次,似乎没有任何限制(例如,我们不必使它独一无二):

>>> P1 = namedtuple('Point', ['x', 'y'])
>>> P2 = namedtuple('Point', ['x', 'y', 'z'])
>>> p1 = P1(1,2)
>>> p2 = P2(1,2,3)
>>> p1
Point(x=1, y=2)
>>> p2
Point(x=1, y=2, z=3)

我在手册或者谷歌搜索中没有找到解释。有一个相关的问题可以在这里找到,但是它没有回答为什么namedtuple需要第一个参数以及如何使用或者何时需要。


2
想一想 - 如果这个类没有 __name__,那么 repr 会是什么样子?如果你设置 ClassName = namedtuple('ClassName', ...),那么你可以使用 eval 来重新创建一个给定的实例。 - jonrsharpe
你认为namedtuple中的name这个词来自哪里? - Padraic Cunningham
@jonrsharpe 我之前对类名有一个误解,我认为它们应该是唯一的。 - WKPlus
@WKPlus 通常情况下,它们应该是这样的,但并不一定要求如此。 - jonrsharpe
1个回答

20

它设置生成的类的名称:

>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
>>> Point
<class '__main__.Point'>
>>> Point = namedtuple('Foobar', ['x', 'y'])
>>> Point
<class '__main__.Foobar'>

你的全局变量中的Point名称只是对生成类的引用,类本身需要一个名称。该名称不能从分配对象的变量中获取,因为类是首先生成的,然后在单独的步骤中分配(在namedtuple()调用返回后)。

它不需要像使用class时那样是唯一的:

>>> class Foo(object):
...     pass
... 
>>> Bar = Foo
>>> class Foo(object):
...     pass
... 
>>> Bar
<class '__main__.Foo'>
>>> Foo
<class '__main__.Foo'>

通常情况下,您可以通过使每个模块的名称唯一来避免这种情况,但这并非必须。

名称用于调试目的;在跟踪和repr()输出中,名称显示为帮助您确定使用了哪个类。

对于Python来说,如果生成的类重新使用名称,则无关紧要。但对于pickle模块来说很重要;如果您需要能够pickle命名元组类实例,请确保选择与pickle稍后可以再次加载它的全局变量相匹配的名称。但是,如果重新使用名称对您有意义或不会积极地妨碍您的代码开发或调试任务,那么请随意重用名称或选择任何您喜欢的名称。


但是当我定义两个具有相同名称的命名元组时,它可以正常工作,为什么? - WKPlus
@WKPlus:我也可以创建多个同名的类或函数。为了调试和清晰起见,您希望将它们保持唯一,但这并没有强制执行。 - Martijn Pieters
两个具有相同名称但包含不同属性的命名元组,它仍然可以工作,这有意义吗? - WKPlus
@WKPlus:如果对于你作为开发者来说没有意义,那就不要使用重复的名称。但在某些情况下,可以很容易地按需生成命名元组类,而名称并不重要,因此为每个生成新的唯一名称也没有意义。 - Martijn Pieters
@WKPlus: 但通常情况下,当你重复使用一个名称时,没有什么会出错。如果您想要将已命名的元组类的实例进行持久化,您需要使用与存储该类的全局名称匹配的名称(这样解封序列化才能够重新找到该类),但总的来说,Python 并不关心 - Martijn Pieters
显示剩余2条评论

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