24

私はnamedtuplesのリストを扱っています。名前付きタプルが作成された後、各タプルにフィールドを追加したいと思います。(のように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')
4

4 に答える 4

21

新しいクラスnamedtuple(...)を返すので、あなたがすることはうまくいきます。実際に Result オブジェクトを取得するには、そのクラスをインスタンス化します。したがって、正しい方法は次のとおりです。

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

また、これらのオブジェクトに属性を追加しても機能しないことがわかります。やってはいけない理由は、効果がないからです。クラス オブジェクトを悪用することだけが機能します。なぜこれが恐ろしい、恐ろしい考えなのかを詳しく説明する必要がないことを願っています。

namedtuple に属性を追加できるかどうかに関係なく (必要なすべての属性を事前にリストしたとしても)、namedtuple オブジェクトを作成後に変更することはできないことに注意してください。タプルは不変です。そのため、作成後に何らかの理由でオブジェクトを変更する必要がある場合、方法や形状を問わず、 を使用することはできませんnamedtuple。カスタム クラスを定義したほうがよいでしょう (namedtuple追加するものの中には、ミュータブル オブジェクトに対して意味をなさないものもあります)。

于 2013-03-10T16:43:43.743 に答える
13

typeここでは、そのタイプのインスタンスではなく、名前付きタプルを変更していることに注意してください。この場合、おそらく古いタイプからフィールドを追加して新しいタイプを作成したいと思うでしょう:

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

例えば:

>>> result = namedtuple('Result',['x','y'])
>>> result = namedtuple('Result',result._fields+('point',))
>>> result._fields
('x', 'y', 'point')
于 2013-03-10T16:43:52.170 に答える
5

名前付きタプルは不変であることを念頭に置いて、簡単に連結できます

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)
于 2018-02-26T21:22:14.237 に答える
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

の値xを出力しpます。

>>> 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)
于 2013-03-10T16:39:02.780 に答える