【问题标题】:how do I add fields to a namedtuple?如何将字段添加到命名元组?
【发布时间】:2013-02-25 19:21:32
【问题描述】:

我正在处理一个命名元组列表。我想在创建每个命名元组后为其添加一个字段。看来我可以通过将其作为属性引用来做到这一点(如namedtuple.attribute = 'foo'),但随后它不会添加到字段列表中。如果我不对字段列表做任何事情,有什么理由不这样做吗?有没有更好的方法来添加字段?

>>> from collections import namedtuple
>>> result = namedtuple('Result',['x','y'])
>>> result.x = 5
>>> result.y = 6
>>> (result.x, result.y)
(5, 6)
>>> result.description = 'point'
>>> (result.x, result.y, result.description)
(5, 6, 'point')
>>> result._fields
('x', 'y')

【问题讨论】:

  • 你为什么不直接使用 dict 呢? dict.keys 肯定会添加“字段”。

标签: python namedtuple


【解决方案1】:

因为namedtuple(...) 返回了一个新类,所以您所做的工作有效。要实际获取 Result 对象,您需要实例化该类。所以正确的做法是:

Result = namedtuple('Result', ['x', 'y'])
result = Result(5, 6)

您会发现向这些对象添加属性并起作用。所以你不应该这样做的原因是因为它不起作用。只有滥用类对象才有效,我希望我不需要详细说明为什么这是一个可怕的想法。

请注意,无论您是否可以向 namedtuple 添加属性(即使您事先列出了所有需要的属性),您都无法在创建 namedtuple 对象后对其进行更改。元组是不可变的。因此,如果您在创建后出于任何原因需要更改对象,以任何方式或形状,您都不能使用namedtuple。你最好定义一个自定义类(namedtuple 为你添加的一些东西甚至对可变对象都没有意义)。

【讨论】:

    【解决方案2】:

    请注意,您在这里修改的是命名元组的type,而不是该类型的实例。在这种情况下,您可能希望使用旧类型的附加字段创建一个新类型:

    result = namedtuple('Result',result._fields+('point',))
    

    例如:

    >>> result = namedtuple('Result',['x','y'])
    >>> result = namedtuple('Result',result._fields+('point',))
    >>> result._fields
    ('x', 'y', 'point')
    

    【讨论】:

      【解决方案3】:

      您可以轻松地连接命名元组,记住它们是不可变的

      from collections import namedtuple
      
      T1 = namedtuple('T1', 'a,b')
      T2 = namedtuple('T2', 'c,d')
      
      t1 = T1(1,2)
      t2 = T2(3,4)
      
      def sum_nt_classes(*args):
          return namedtuple('_', ' '.join(sum(map(lambda t:t._fields, args), ())))
      
      def sum_nt_instances(*args):
          return sum_nt_classes(*args)(*sum(args,()))
      
      print sum_nt_classes(T1,T2)(5,6,7,8)
      print sum_nt_instances(t1,t2)
      

      【讨论】:

      • 这些函数的含义很难理解,能否请您扩展一下?为什么要对命名元组的字段求和?
      【解决方案4】:

      在定义 namedtuple 后,您无法将新字段添加到它。唯一的方法是创建一个新模板并创建新的namedtuple 实例。

      分析

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

      result 不是元组,而是创建元组的类。

      >>> result.x
      <property object at 0x02B942A0>
      

      你像这样创建一个新的元组:

      >>> p = result(1, 2)
      >>> p
      Result(x=1, y=2)
      
      >>> p.x
      1
      

      p 中打印值x

      >>> p.x = 5
      
      Traceback (most recent call last):
        File "<pyshell#10>", line 1, in <module>
          p.x = 5
      AttributeError: can't set attribute
      

      这会引发错误,因为元组是不可变的。

      >>> result.x = 5
      >>> result
      <class '__main__.Result'>
      >>> result._fields
      ('x', 'y')
      >>> p = result(1, 2)
      >>> p
      Result(x=1, y=2)
      

      这不会改变任何事情。

      >>> result.description = 'point'
      >>> result
      <class '__main__.Result'>
      >>> result._fields
      ('x', 'y')
      

      这也不会改变任何东西。

      解决方案

      >>> result = namedtuple('Result', ['x','y'])
      >>> p = result(1, 2)
      >>> p
      Result(x=1, y=2)
      >>> # I need one more field
      >>> result = namedtuple('Result',['x','y','z'])
      >>> p1 = result(1, 2, 3)
      >>> p1
      Result(x=1, y=2, z=3)
      >>> p
      Result(x=1, y=2)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-12-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-01
        相关资源
        最近更新 更多