1. ホーム
  2. python

[解決済み] Pythonの「名前付きタプル」とは何ですか?

2022-03-18 22:51:50

質問

を読む Python 3.1での変更点 意外なことがわかりました。

<ブロッククオート

sys.version_infoタプルは、現在では 名前付きタプル :

名前付きタプルのことは初めて知りました。また、要素のインデックスは、タプルやリストのように数値で指定するか、ディクスのようにキーで指定するかのどちらかだと思っていました。まさか両方の方法でインデックスを付けられるとは思ってもみませんでした。

したがって、私の質問は

  • 名前付きタプルとは何ですか?
  • どのように使用するのですか?
  • なぜ、どのような場合に通常のタプルではなく名前付きタプルを使用する必要があるのですか?
  • なぜ、どのような場合に名前付きタプルではなく、通常のタプルを使用する必要があるのですか?
  • 名前付きリスト(名前付きタプルの変更可能バージョン)のようなものはありますか?

どのように解決するのですか?

名前付きタプルは、基本的に簡単に作成できる軽量なオブジェクト型です。 名前付きタプルのインスタンスは、オブジェクトのような変数デリファレンスや標準的なタプルの構文を使って参照することができます。 これらは、以下のように使用することができます。 struct などの一般的なレコード型がありますが、イミュータブルである点が異なります。 Python 2.6とPython 3.0で追加されましたが、Python 3.0には Python 2.4 での実装のためのレシピ .

例えば、点をタプルとして表現することはよくあります。 (x, y) . これは、以下のようなコードになる。

pt1 = (1.0, 5.0)
pt2 = (2.5, 1.5)

from math import sqrt
line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)

名前付きタプルを使うと、より可読性が高くなります。

from collections import namedtuple
Point = namedtuple('Point', 'x y')
pt1 = Point(1.0, 5.0)
pt2 = Point(2.5, 1.5)

from math import sqrt
line_length = sqrt((pt1.x-pt2.x)**2 + (pt1.y-pt2.y)**2)

しかし、名前付きタプルは通常のタプルと後方互換性があるため、以下はまだ動作します。

Point = namedtuple('Point', 'x y')
pt1 = Point(1.0, 5.0)
pt2 = Point(2.5, 1.5)

from math import sqrt
# use index referencing
line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)
 # use tuple unpacking
x1, y1 = pt1

このように オブジェクト記法があなたのコードをよりPythonicで読みやすくすると思う場合は、タプルの代わりに名前付きタプルを使用する必要があります。 . 私自身は、特に関数にパラメータとして渡すとき、非常に単純な値の型を表現するために使うようになりました。 これは、タプルパッキングのコンテキストを見ることなく、関数をより読みやすくするものです。

さらに また、通常の 不変 関数を持たないクラス を持つフィールドのみです。 名前付きタプル型をベースクラスとして使用することもできます。

class Point(namedtuple('Point', 'x y')):
    [...]

ただし、タプルと同様、名前付きタプルの属性は不変である。

>>> Point = namedtuple('Point', 'x y')
>>> pt1 = Point(1.0, 5.0)
>>> pt1.x = 2.0
AttributeError: can't set attribute

値を変更できるようにしたい場合は、別の型が必要です。 の便利なレシピがあります。 ミュータブルレコードタイプ を使用すると、属性に新しい値を設定することができます。

>>> from rcdtype import *
>>> Point = recordtype('Point', 'x y')
>>> pt1 = Point(1.0, 5.0)
>>> pt1 = Point(1.0, 5.0)
>>> pt1.x = 2.0
>>> print(pt1[0])
    2.0

しかし、新しいフィールドを追加できるような "named list" の形式を私は知りません。 このような状況では、辞書を使用するのがよいでしょう。名前付きタプルは次のようにして辞書に変換できます。 pt1._asdict() を返します。 {'x': 1.0, 'y': 5.0} であり、通常のすべての辞書関数で操作できる。

すでに述べたように ドキュメントを確認する は、これらのサンプルを作成した際の詳細な情報です。