質問

私は今、授業のために Python を学んでいます。データ型の 1 つとしてタプルについて説明したところです。Wikipedia のページを読みましたが、そのようなデータ型が実際にどのような用途に役立つのかわかりませんでした。おそらく Python で、不変の数値セットが必要となる例をいくつか挙げていただけますか?これはリストとどう違うのでしょうか?

役に立ちましたか?

解決

  • タプルは、関数から複数の結果を返したい場合に使用されます。
  • これらは不変であるため、辞書のキーとして使用できます (リストは使用できません)。

他のヒント

タプルは、複数のデータをキーに結合する必要があるが、そのクラスを作成する気がない場合に優れた辞書キーを作成します。

a = {}
a[(1,2,"bob")] = "hello!"
a[("Hello","en-US")] = "Hi There!"

私はこの機能を主に、メッシュの頂点の座標であるキーを含む辞書を作成するために使用しました。ただし、私の特定のケースでは、関連する浮動小数点の正確な比較は正常に機能しましたが、目的には必ずしも当てはまらない可能性があります[その場合は、受信した浮動小数点数をある種の固定小数点整数に変換することになるでしょう]

好き この説明.

基本的に、定数構造がある場合はタプルを使用する必要があり (最初の位置には常に 1 つのタイプの値が保持され、2 番目の位置には別のタイプの値が保持されるなど)、同種の値のリストにはリストを使用する必要があります。

もちろん例外は常にありますが、これは一般的なガイドラインとしては適切です。

タプルとリストは一般に同じ用途があります。一般に、不変データ型には多くの利点がありますが、主に同時実行性の問題に関してです。

したがって、本質的に揮発性ではないリストがあり、コンシューマがそれを変更していないことを保証する必要がある場合は、タプルを使用できます。

典型的な例は、会社の部門、カテゴリなどのアプリケーション内の固定データです。このデータが変更された場合、通常は単一のプロデューサーがタプルを再構築します。

それについて考える最良の方法は次のとおりです。

  • タプルとは、 記録 そのフィールドには名前がありません。
  • フィールド名を指定するのが面倒な場合は、レコードの代わりにタプルを使用します。

したがって、次のようなことを書く代わりに:

person = {"name": "Sam", "age": 42}
name, age = person["name"], person["age"]

または、さらに冗長になります:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

person = Person("Sam", 42)
name, age = person.name, person.age

次のように書くことができます。

person = ("Sam", 42)
name, age = person

これは、フィールドが 2 つだけあるレコード、またはいくつかの場所でのみ使用されるレコードを渡したい場合に便利です。その場合、フィールド名を使用してまったく新しいレコード タイプを指定すると (Python では、上記のようにオブジェクトまたは辞書を使用します)、冗長すぎる可能性があります。

タプルは関数型プログラミングの世界から生まれました (Haskell、OCaml、Elm、F# など)。これらはこの目的で一般的に使用されます。Python とは異なり、ほとんどの関数型プログラミング言語は静的に型指定されます (変数は 1 種類の値のみを保持でき、その型はコンパイル時に決定されます)。静的型付けにより、タプルの役割がより明確になります。たとえば、Elm 言語では次のようになります。

type alias Person = (String, Int)

person : Person
person = ("Sam", 42)

これは、特定のタイプのタプルには常に固定順序で固定数のフィールドが含まれ、それらの各フィールドは常に同じタイプであることが想定されているという事実を強調しています。この例では、人物は常に 2 つのフィールドのタプルであり、1 つは文字列で、もう 1 つは整数です。

上記はリストとはまったく対照的です, これらは可変長であると想定されており (項目の数は通常、各リストで異なり、項目を追加および削除する関数を作成します)、リスト内の各項目は通常は同じ型です。たとえば、人物のリストと住所の別のリストがあるとします。同じリスト内に人物と住所を混在させることはできません。同じタプル内で異なるタイプのデータを混合することがタプルの重要な点です。タプル内のフィールドは通常、さまざまなタイプになります (ただし、常にそうとは限りません - 例:あなたは持つことができます (Float, Float, Float) x、y、z 座標を表すタプル)。

タプルとリストは入れ子になることがよくあります。 タプルのリストを持つのが一般的です。人物オブジェクトのリストだけでなく、人物タプルのリストも持つことができます。値がリストであるタプル フィールドを持つこともできます。たとえば、1 人が複数のアドレスを持つことができるアドレス帳がある場合、次のタイプのタプルを作成できます。 (Person, [String]). 。の [String] type は関数型プログラミング言語で文字列のリストを表すためによく使用されます。Python では、型を書き留めることはありませんが、まったく同じ方法でそのようなタプルを使用できます。 Person タプルの最初のフィールドにオブジェクト、2 番目のフィールドに文字列のリスト。

Pythonでは混乱が生じる 言語はそうじゃないから 強制する 静的に型付けされた関数型言語のコンパイラーによって強制されるこれらのプラクティス。これらの言語では、異なる種類のタプルを混合することはできません。たとえば、 (String, String) を返すという型の関数からのタプル (String, Integer) タプル。また、型がタプルを返す予定である場合にリストを返すことはできません。また、その逆も同様です。リストは項目のコレクションを増大させるためにのみ使用され、タプルは固定サイズのレコードにのみ使用されます。Python では、これらのルールを破ろうと思えば、それを妨げることはありません。

Python では、Python の辞書キーは不変である必要があるため、リストは辞書キーとして使用するタプルに変換されることがあります。定数) 値であるのに対し、Python リストは変更可能です (項目はいつでも追加および削除できます)。これは Python の特定の制限に対する回避策であり、コンピューター サイエンスの概念としてのタプルの特性ではありません。

したがって、Python では、リストは変更可能であり、タプルは不変です。ただし、これは単なる設計上の選択であり、コンピューター サイエンスにおけるリストとタプルの本質的な特性ではありません。不変リストと可変タプルを使用することもできます。

Python (デフォルトの CPython 実装を使用) では、タプルはほとんどの目的でオブジェクトや辞書より高速であるため、オブジェクトや辞書を使用してフィールドに名前を付ける方が明確な場合でも、その理由でタプルが使用されることがあります。

最後に、タプルが (別の種類のリストではなく) 別の種類のレコードであることをさらに明確にするために、Python には次の機能もあります。 名前付きタプル:

from collections import namedtuple

Person = namedtuple("Person", "name age")

person = Person("Sam", 42)
name, age = person.name, person.age

多くの場合、これが最良の選択です。新しいクラスを定義するよりも短くなりますが、フィールドの意味は、フィールドに名前のない通常のタプルを使用する場合よりも明白です。

不変リストはさまざまな目的に非常に役立ちます, 、しかし、このトピックはここで答えるにはあまりにも複雑すぎます。重要な点は、変化できないものは、変化するものよりも推論しやすいということです。ソフトウェアのバグのほとんどは、予期しない方法で変化することから発生するため、バグを排除するには、変化の可能性を制限することが良い方法です。興味があれば、Elm、Haskell、Clojure などの関数型プログラミング言語のチュートリアルを読むことをお勧めします (Elm が最も親しみやすいです)。これらの言語の設計者は、不変性が非常に有用であると考えていました。 全て そこではリストは不変です。(リストを変更して項目を追加または削除する代わりに、 項目を追加または削除して新しいリストを作成する. 。不変性により、リストの古いコピーが決して変更されないことが保証されるため、コンパイラとランタイムは、古いリストの一部を新しいリストで再利用し、リストが長くなった場合に残った部分をガベージ コレクションすることで、コードのパフォーマンスを向上させることができます。必要です。)

常に 2 つ以上のオブジェクトをセットとして扱う場合に便利だと思います。

タプルは値のシーケンスです。値は任意の型にすることができ、整数によってインデックスが付けられるため、タプルはリストとは異なります。最も重要な違いは、 タプルは不変です。

タプルは、カンマで区切られた値のリストです。

t = 'p', 'q', 'r', 's', 't'

タプルを括弧で囲むことをお勧めします。

t = ('p', 'q', 'r', 's', 't') 

機能に関しては、リストは常にタプルを置き換えることができます (辞書内のキーとしての場合は除く)。ただし、タプルを使用すると処理を高速化できます。同じことが、たとえば Java の不変文字列にも当てはまります。文字列を変更できない必要が生じるのはいつでしょうか?一度もない!

より良いプログラムを作成するためにできることを制限することについてのまともな議論を読みました。 関数型プログラミングが重要な理由 重要な理由

タプルは複数の値を保存するのに便利です。お気づきのように、タプルは不変のリストに似ています。一度作成すると、要素を追加/削除/交換することはできません。

不変であることの利点の 1 つは、タプルが固定サイズであるため、ランタイムが特定の最適化を実行できることです。これは、タプルが関数の戻り値またはパラメータのコンテキストで使用される場合に特に有益です。

文字列 % 操作や複数の戻り値など、構文的に必要な場所に加えて、軽量クラスの形式としてタプルを使用します。たとえば、あるメソッドから呼び出し元に不透明な Cookie を渡し、それが別のメソッドに渡されるオブジェクトがあるとします。タプルは、複数の値を含めるための別のクラスを定義することなく、その Cookie に複数の値をパックする良い方法です。

ただし、この特定の用途については慎重になるよう努めています。Cookie がコード全体で多量に使用される場合は、その使用法を文書化するのに役立つため、クラスを作成することをお勧めします。1 か所でのみ使用されている場合 (例:1 組のメソッド)の場合は、タプルを使用するかもしれません。いずれの場合も、これは Python であるため、呼び出し元のコードを変更することなく、タプルから開始して、それをカスタム クラスのインスタンスに変更できます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top