質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

4回答

2471閲覧

tupleとlistの違い

gontaros0302

総合スコア14

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

2クリップ

投稿2018/05/31 09:39

tupleとlistの違いとして、
① tupleは変更不可だから緯度のような不変のものに使える
② listよりもパフォーマンスが良い(実行速度が少し早い)
とwebに書いていました。

しかし、別のtupleを作って連結することで要素の追加のような振る舞いができる。ともあったのですが

要は、

python

1tuple_player = (‘honda’, ‘kagawa’, ‘Hasebe 2)

のようなtupleがあった時に、そのものが変更できないという理解で正しいのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

LouiS0616さんの回答されている点をまず理解するのが基本と思います。その上で

別のtupleを作って連結することで要素の追加のような振る舞いができる。ともあったのですが

正確にいえば「一度生成したtupleは要素を違う値に置き換えたり、別のtupleを直接連結できない」です。「別のtupleを作って連結する」の正確な意味は「一旦作ったtuple(A)に別のtuple(B)をくっつけたかのような新たなtuple(C)を作り出すことができる」ということです。

python

1a = (1, 2) 2b = a 3a += (3,) 4print(a) # (1, 2, 3) 5print(b) # (1, 2)

つまり
a += (3,)
は以下のように書いたのと同じ動作になり
a = a + (3,)
右辺を計算すると新たなtupleが作られ、それを変数aへ代入しているだけなのです。
aにあった元のtupleの値が変化するわけではありません。

一方listは違います。

python

1a = [1, 2] 2b = a 3a += [3] 4print(a) # [1, 2, 3] 5print(b) # [1, 2, 3]

つまり
a += [3]
はaに格納されていたlistそのものを改変して要素をくっつける意味になっています。tupleと異なりlistはa += [3]a = a + [3]の振る舞いが違っているのですね。

これはpythonの言語仕様がそうなっているわけではなくlistの__iadd__メソッドが

いやーわざわざ新しいlistインスタンスつくるのメモリーがもったいないし、自分自身の箱(要素を保持しておく場所)をぐいっと伸ばして+=の右側に指定したlistの中身をそこへ代入しちまえばいいやー!

といった定義になっているのです。これはlistのextendメソッドでも同じようなことができます。
a.extend([3])

tupleは絶対に自分自身を書き換えません。「tupleの値 + tupleの値」という演算をすると毎回新たなtupleを作り出しているのですね。それゆえextendのようなメソッドもありません。

見かけ上listもtupleも
a += b
で連結できるかのように感じますが、listは一々新たなインスタンスを生成しないのに対してtupleで上記のようなことをやっても毎回新たなインスタンスを計算しているわけでlistに比べて効率が若干悪くなります。

python

1def foo(a, b, n): 2 for _ in range(n): 3 a += b 4 5def run(f): 6 import time 7 t = time.time() 8 f() 9 return time.time() - t 10 11run(lambda : foo([1, 2, 3], [1, 2, 3], 1000)) # 0.00011658668518066406 12run(lambda : foo((1, 2, 3), (1, 2, 3), 1000)) # 0.004464626312255859

(訂正:コピペミスで2番目のrunの引数をtupleじゃなくてlistかのように書いていました。訂正してお詫びいたします。)
この例ではlistの方がtupleより一けた早いことがわかります。ただちいさな要素数のものをちょこっと連結するだけなら、こんな点をそう気にする必要もないと思います。

投稿2018/05/31 10:31

編集2018/05/31 12:20
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gontaros0302

2018/05/31 10:55

ありがとうございます???? たしかに、見かけ上はリストもタプルもそれぞれ連結できるからほぼ同じといっても過言じゃないなと認識しますが タプルは最初に言ったことは断固として変えない頑固親父みたいな感じで、リストは最初に言ったことを誰かに指摘されたり補足してもらうと『そうなんだ』とアップグレードしなおして発言する母のような感じですね。(例えとして良いのかわかりませんが)
KSwordOfHaste

2018/05/31 10:59

まさにそういう理解でよいと思います~ 断固として値を変えないおやじにはよい点があり、他のメソッドの引数にどうわたそうが呼び元では「この値は絶対に変わらない」と安心できることです。頑固なのはときとして貴重な利点になるといえるでしょう。
gontaros0302

2018/05/31 11:20

本当に勉強になります!????
guest

0

解決済みの質問ですが・・・

pythonのオブジェクトには固有のidが割り振られています。同じオブジェクトならidが変わることはありませんし、同時に存在する異なるオブジェクトが同じidになることもありません。CPython(普通に使われているpythonです)の実装では、idはメモリ上のアドレスと等価です。

2. 組み込み関数 — Python 3.6.5 ドキュメント

idは組み込み関数id()で確認できます。これを使うと簡単に「listとtupleの違い」を確認することができます。

python

1>>> lst = [1,2,3] 2>>> id(lst) 3139687300282696 4>>> lst += [4,5,6] 5>>> id(lst) 6139687300282696 # 変わらない 7>>> tup = (1,2,3) 8>>> id(tup) 9139687181137384 10>>> tup += (4,5,6) 11>>> id(tup) 12139687181105000 # 変わった

「結果は同じようなものなんだから、どっちを使っても良い?」という話もありますが、あまり良くないです。
元の変数とは別に、同じものを参照する変数を用意するとすぐわかります。

python

1>>> lst = [1,2,3] 2>>> lst_ref = lst 3>>> lst += [4,5,6] 4>>> lst 5[1, 2, 3, 4, 5, 6] 6>>> lst_ref 7[1, 2, 3, 4, 5, 6] 8>>> tup = (1,2,3) 9>>> tup_ref = tup 10>>> tup += (4,5,6) 11>>> tup 12(1, 2, 3, 4, 5, 6) 13>>> tup_ref 14(1, 2, 3)

この違いは常に意識しておかないと、危ないと言えます。参照(ポインタみたいなもの:すべての実体は参照によって示される以外の方法では存在しない)と実体(いわゆるインスタンス)がどう結びついているのかをしっかり理解しないと、まともに動くコードは書けません。
ま、オブジェクト指向言語って、そういうものです。

それと、より実際的な問題として、listは辞書のキーやsetの要素になれません。tupleはなれます。
この違いはmutable(可変)かimmutable(不変)かによるものです。
まあ、辞書のキーにリストが使えたら、キーに直接appendするだけでえらい騒ぎになってしまいますから・・・

投稿2018/05/31 12:46

hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

『要素が変更できない』とは、つまり次のような違いです。

Python

1>>> lst = [1, 2, 3, 4, 5] 2>>> lst[0] = 42 3>>> 4>>> print(lst) 5[42, 2, 3, 4, 5]

Python

1>>> tpl = (1, 2, 3, 4, 5) 2>>> tpl[0] = 42 3Traceback (most recent call last): 4 File "<stdin>", line 1, in <module> 5TypeError: 'tuple' object does not support item assignment 6>>> 7>>> print(tpl) 8(1, 2, 3, 4, 5)

実際には、次のような使い分けがあるような。

  • 同じ型のオブジェクトを扱う ⇒ リスト
  • 違う型のオブジェクトを扱う ⇒ タプル

リストは配列、タプルは構造体に近い使われ方をしているように思います。

タプルはリストと似ていますが、たいてい異なる場面と異なる目的で利用されます。タプルは不変型 (immutable) で、複数の型の要素からなることもあり、要素はアンパック(この節の後半に出てきます)操作やインデックス (あるいは namedtuples の場合は属性)でアクセスすることが多いです。一方、リストは変更可能 (mutable) で、要素はたいてい同じ型のオブジェクトであり、たいていイテレートによってアクセスします。

引用元: Python チュートリアル » タプルとシーケンス

参考

英語ですけれど、深まった議論がなされています。
Stack Overflow - What's the difference between lists and tuples?

Apart from tuples being immutable there is also a semantic distinction that should guide their usage. Tuples are heterogeneous data structures (i.e., their entries have different meanings), while lists are homogeneous sequences. Tuples have structure, lists have order.

投稿2018/05/31 09:44

編集2018/05/31 09:55
LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gontaros0302

2018/05/31 10:23

ありがとうございます! 別の質問かもしれませんが、 a = (1, 2, 3) とだけ入力した際 aはリストなのかタプルなのかがわかりません。
LouiS0616

2018/05/31 10:26

それはタプルですね。 リストなら a = [1, 2, 3] と書きます。 なお、実は a = 1, 2, 3 とも書けます。これはタプルです。
ikapy

2018/05/31 10:30

type(a)で確認できますよ。 In [1]: a = (1, 2, 3) In [2]: type(a) Out[2]: tuple となりました。
gontaros0302

2018/05/31 10:38

なるほど!ありがとうございます???? そもそもの書き方ですね。 リストは[ ] タプルは( ) or 無 ということでしょうか?
LouiS0616

2018/05/31 10:41

@ikapy さん 補足ありがとうございます。 @gontaros0302 さん 基本的には、リストは[ ]、タプルは( ) です。 ( )が省略できる場面がたまにあり、積極的に利用しなければならないわけではありませんが、知っておくと何かと便利です。
ikapy

2018/05/31 10:42

ということですね。
gontaros0302

2018/05/31 10:48

@ikapy さん ありがとうございます???? @LouiS0616 さん 丁寧に解説していただき、ありがとうございます????
guest

0

【インデックス】を指定した【中身】の書き換えは不可能という認識でいいと思います。

全体の書き換えは出来ます。

python

1x = (0, 1, 2) 2x = 10 3print(x) #10

python

1x = (0, 1, 2) 2x += (3, 4, 5) 3print(x)#(0, 1, 2, 3, 4, 5)

python

1x = (0, 1, 2) 2x[0] = 1 #エラー

投稿2018/05/31 09:47

puroko3

総合スコア185

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gontaros0302

2018/05/31 10:25

なるほど、わかりやすい回答ありがとうございます。段ボール箱にみかん、りんご、桃が入っていたら、追加でキウイいれたりバナナを入れることはできるけれど、りんごをナシに変更するのはダメだよってことですね。
puroko3

2018/05/31 10:57

概ねそんな感じですが厳密には少し異なります。 こんがらないように言わないべきかと思いましたが 既に他の回答者さんがそれらしき事に触れているので一応 リストにみかん、りんご、桃を入れた後にキウイやバナナを入れるとします(appendを使って)。当然ですが今ある段ボールに対してそのまま追加でいれます。 しかしタプルで追加した場合は、一度わざわざ段ボールを潰し、入ってあった果物を全て捨ててから新たに段ボールを用意して、果物を入れていきます。 自身を書き換えないというのはそういう事で パフォーマンスが低下する事があるのもその為です。 一見奇妙に感じるかもしれませんが、そうした方がバグを生みにくかったりするのです。
gontaros0302

2018/05/31 11:18

一度オジャンにするんですねー。 本当にtupleは頑固ですね。。笑
puroko3

2018/05/31 11:29

というよりリストや辞書を除いてpythonの型は大体そんな感じになっています。str型・int型・float型・tuple型 この辺りは新しい物を作る時は、段ボールを一度潰してから的な事をやっています。 まあもう既に解決済みなのでこの辺でw
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問