namedtuple中typename的相关性

46 投票
3 回答
5599 浏览
提问于 2025-04-18 00:40
from collections import namedtuple

Point = namedtuple('whatsmypurpose',['x','y'])
p = Point(11,22)
print(p)

输出:

whatsmypurpose(x=11,y=22)

‘whatsmypurpose’这个东西有什么用处或者关系呢?

3 个回答

4

考虑一下:

class MyClass(tuple):
   pass

这段代码创建了一个类型,它是一个元组的子类,并且它有一个名字,MyClass.__name__ == "MyClass"namedtuple是一个类型工厂,它也会创建元组的子类,但在这个函数式的用法中,你需要明确地传入名字。

当你把返回的类型赋值给一个不同的名字时:

Point = namedtuple('whatsmypurpose',['x','y'])

这就像是做了以下操作:

class whatsmypurpose(tuple):
    ... # extra stuff here to setup slots, field names, etc

Point = whatsmypurpose
del whatsmypurpose

在这两种情况下,你只是给这个类型起了一个不同的别名。

通常,你会把它赋值为和类型名字相同的名字。如果你觉得重复同样的字符串不符合DRY原则,那么你可以使用typing.NamedTuple中的声明式API,而不是collections中的函数式API。不过那样的话,你可能还得烦恼需要注解类型的问题。

9

'whatsmypurpose' 是给新创建的子类起的名字。根据文档的说明:

collections.namedtuple(typename, field_names, verbose=False, rename=False)
这个函数会返回一个新的元组子类,名字就是 typename

下面是一个例子:

>>> from collections import namedtuple
>>> Foo = namedtuple('Foo', ['a', 'b'])
>>> type(Foo)
<class 'type'>
>>> a = Foo(a = 1, b = 2)
>>> a
Foo(a=1, b=2)
>>> Foo = namedtuple('whatsmypurpose', ['a', 'b'])
>>> a = Foo(a = 1, b = 2)
>>> a
whatsmypurpose(a=1, b=2)
>>> 

如果把 verbose 参数设置为 True,你就可以看到完整的 whatsmypurpose 类的定义。

>>> Foo = namedtuple('whatsmypurpose', ['a', 'b'], verbose=True)
from builtins import property as _property, tuple as _tuple
from operator import itemgetter as _itemgetter
from collections import OrderedDict

class whatsmypurpose(tuple):
    'whatsmypurpose(a, b)'

    __slots__ = ()

    _fields = ('a', 'b')

    def __new__(_cls, a, b):
        'Create new instance of whatsmypurpose(a, b)'
        return _tuple.__new__(_cls, (a, b))

    @classmethod
    def _make(cls, iterable, new=tuple.__new__, len=len):
        'Make a new whatsmypurpose object from a sequence or iterable'
        result = new(cls, iterable)
        if len(result) != 2:
            raise TypeError('Expected 2 arguments, got %d' % len(result))
        return result

    def _replace(_self, **kwds):
        'Return a new whatsmypurpose object replacing specified fields with new values'
        result = _self._make(map(kwds.pop, ('a', 'b'), _self))
        if kwds:
            raise ValueError('Got unexpected field names: %r' % list(kwds))
        return result

    def __repr__(self):
        'Return a nicely formatted representation string'
        return self.__class__.__name__ + '(a=%r, b=%r)' % self

    def _asdict(self):
        'Return a new OrderedDict which maps field names to their values.'
        return OrderedDict(zip(self._fields, self))

    def __getnewargs__(self):
        'Return self as a plain tuple.  Used by copy and pickle.'
        return tuple(self)

    a = _property(_itemgetter(0), doc='Alias for field number 0')

    b = _property(_itemgetter(1), doc='Alias for field number 1')
12

namedtuple() 是一个用来创建 tuple 子类的工厂函数。在这里,'whatsmypurpose' 是类型名称。当你创建一个命名元组时,内部会生成一个名为 whatsmypurpose 的类。

你可以通过使用详细参数来观察这一点,像这样:

Point=namedtuple('whatsmypurpose',['x','y'], verbose=True)

你也可以尝试 type(p) 来验证这一点。

撰写回答