Pythonのデータ型について知ろうの会
この記事ではPythonにおけるデータ型の基礎は押さえているが
それぞれどんな特徴があり、どのような使い方があるのかを改めて理解することを目的とします。
筆者が思うデータ型の重要性
個人的にはPythonを学ぶ上で「データ型の理解」が最も重要なポイントだと考えています。
初心者がよく遭遇するエラーとして、以下の2つが挙げられます。
- TypeError: 処理しようとしているオブジェクト同士のデータ型が一致しない
- SyntaxError: Pythonの文法が誤っている
特にTypeErrorが頻繁に発生する場合は、データ型の理解が不十分であることが原因です。
データ型を正しく理解することで、TypeErrorを避けやすくなり、より効率的なコーディングが可能になります。
Pythonは変数にデータ型を明示的に宣言しなくても使えるため、「シンプルで使いやすい」とよく言われます。
しかしこれは裏を返せば、「開発者がデータ型を正しく理解していること」が前提とされた設計だとも言えるでしょう。
データ型のクラスとメソッド
Pythonのデータ型とはクラスであり、それぞれ「関数(メソッド)」と「性質(特性)」が備わっています。
データ型がクラスって?
変数のデータ型を確認したいときは、下記のようにtype関数を使って変数のデータ型を標準出力に出力します。
これは厳密にはオブジェクトのクラス(型)を返しているのです。
hoge = "Hello"
print(type(hoge))
<class 'str'>
Pythonを勉強し始めたころは理解できなかったと思いますが、改めて出力結果見ると確かにクラスであることが分かったはずです。
データ型の関数(メソッド)
クラスということは当然メソッドも存在します。
これは各データ型(クラス)によって異なります。
例えば文字列型とリスト型を比べたとき、文字列型はappend()を使えませんが、リスト型はappend()を使うことができます。
このようにデータ型にはそれぞれのデータ型の値を効率的に扱うためのメソッドが定義されています。
このセクションではひとまず「へー、データ型によって使える関数って違うのか」くらいに思っておけば大丈夫です。
データ型の性質
データ型の性質って?
ここ特に重要です。
データ型にはそれぞれ性質が備わっています。
代表的な性質として、イミュータブル、ミュータブル、イテラブル、シーケンスが挙げられます。
- イミュータブル: 同じオブジェクトのデータの変更ができない
- ミュータブル: 同じオブジェクトのデータの変更ができる
- シーケンス: 整数のインデックスを指定することでオブジェクトの要素にアクセスできる
- イテラブル: オブジェクトの要素を1ずつ返すことができる
またデータ型によっては複数の性質を持っている場合があります。
下記はそれをまとめた表です。
組み込み型 (built-in types) | 変更不可 (immutable) | 変更可 (mutable) | 反復可 (iterable) | シーケンス (sequence) | マッピング (mapping) | データ (data) |
---|---|---|---|---|---|---|
bool | ◎ | True, False | ||||
int | ◎ | 整数 | ||||
float | ◎ | 浮動小数点数 | ||||
complex | ◎ | 複素数 | ||||
str | ◎ | ◎ | ◎ | 文字列 | ||
list | ◎ | ◎ | ◎ | |||
tuple | ◎ | ◎ | ◎ | |||
range | ◎ | ◎ | ◎ | |||
dict | ◎ | ◎ | ◎ | |||
set | ◎ | ◎ | ||||
bytes | ◎ | ◎ | ◎ | バイナリ | ||
bytearray | ◎ | ◎ | ◎ | |||
file object | ◎ |
イミュータブル
性質としてはシンプルですが、最初は理解が難しいでしょう。
Python初心者の多くは、次のようなコードで変数x
の値が書き換えられていると思うはず。
x = "hello"
x = "world"
しかしこの2つの変数x
は全く違うオブジェクトになります。
id関数を使ってそれぞれのオブジェクトのIDを確認すると、次のようになります。
x = "hello"
print(id(x))
x = "world"
print(id(x))
4311897200 # x = "hello"
4311896880 # x = "world"
このように出力結果として全く違うオブジェクトであることが分かりました。
つまりどういうことかというと
上記のコードは変数x
の値を置き換えているようで、実は「全く新しいオブジェクトを生成している」のです。
これは文字列型がイミュータブルという性質を持っているためであり
「同じオブジェクトのデータの変更ができない」 ということが分かったと思います。
ミュータブル
イミュータブルと違い、同じオブジェクトのデータを変更することが可能です。
この性質を備えた代表的なデータ型はリスト型と辞書型です。
ではリスト型を例にオブジェクトIDがどのようになっているか見ていきましょう。
リスト型のオブジェクトに値を定義し、その後aaa
をddd
に置き換えます。
x = ["aaa", "bbb", "ccc"]
print(id(x))
x[0] = "ddd"
print(id(x))
4378105536
4378105536
イミュータブルである文字列型と違い、オブジェクトのデータを変更することができます。
シーケンス
整数のインデックスを指定することでオブジェクトの要素を取り出したり、変更したりできます。
代表的なシーケンスのデータ型として、文字列型とリスト型があります。
ここで重要なのが、要素のインデックスは「0」から始まるということです。
x = ["aaa", "bbb", "ccc"]
print(x[0])
print(x[1])
print(x[2])
aaa
bbb
ccc
このようにシーケンスの性質を持つデータ型の変数のインデックスを指定することで任意の値にアクセスすることができます。
またオブジェクトがミュータブルなのであれば値を変更することもできます。
x = ["aaa", "bbb", "ccc"]
x[0] = "ddd"
print(x)
['ddd', 'bbb', 'ccc']
次にリスト型と同じように文字列型の要素にアクセスし、データを変更することはできるか見ていきましょう。
x = "hello"
x[0] = "a"
x[0] = "a"
~^^^
TypeError: 'str' object does not support item assignment
結果としてTypeErrorが返されます。
理由として文字列型はシーケンスの性質を持っているが、同時にイミュータブル(変更不可)でもあるため、
要素にアクセスはできるが、値の変更まではできないことを意味しています。
このようにデータ型は複数の性質を持ち合わせることがあるため注意が必要です。
なおデータの変更ができないだけで、参照したり出力することは可能です。
x = "hello"
print(x[0])
h
イテラブル
要素を1つずつ返すことができるオブジェクトのことを指します。
代表的なイテラブルのデータ型として、文字列型、リスト型、辞書型があります。
この性質の主な利用方法はfor文
です。
for文でTypeError
がよく発生する原因として、繰り返し元のオブジェクトがイテラブルであるかどうかの判断ができていないことが多いです。
x = ["aaa", "bbb", "ccc"]
for hoge in x:
print(hoge)
aaa
bbb
ccc
結果として、変数x
の要素を1つずつhoge
に渡して標準出力に出力する処理を変数x
の「要素の数」だけループします。
イテラブルではない整数型でどうなるかみてみましょう。
x = 10
for hoge in x:
print(x)
for hoge in x:
TypeError: 'int' object is not iterable
結果として、整数型はイテラブルではないというエラーが返されます。
これは整数型がイテラブルの性質を持っていないからです。
各データ型の基礎
文字列型(str)
シングルクォート(')またはダブルクォート(")で囲まれた値は、すべて文字列型(str)として扱われます。
x = "hello"
print(type(x))
<class 'str'>
- 主な性質
- イミュータブル
- シーケンス
- イテラブル
- 主なメソッド
- join()
- replace()
整数型(int)
整数で記載したデータが整数型として定義されます。
Pythonではint
とfloat
の混合計算も自動的に処理され、int型がfloat型に型昇格されて計算が行われます。
x = 10
print(type(x))
```bash:出力
<class 'int'>
- 主な性質
- 整数型はイミュータブルのみです
- 主なメソッド
- メソッドは存在するが、使用頻度が少ないため割愛
浮動小数型(float)
浮動小数で記載したデータが浮動小数型として定義されます。
x = 3.30
print(type(x))
<class 'float'>
- 主な性質
- 浮動小数型はイミュータブルのみです
- 主なメソッド
- メソッドは存在するが、使用頻度が少ないため割愛
リスト型(list)
[]
(スクエアブラケット)で囲まれたデータがリスト型として定義されます。
要素はそれぞれインデックスを持っており、そのインデックスを指定することで要素にアクセスすることができます。
主に処理に必要なデータ(要素)が少ない場合に使用します。
要素の順番に意味がある場合や、順序通りにデータを処理したい場合に適しています。
ただし要素が多すぎるとインデックスの管理が難しくなるため、その場合は辞書型を使う方がわかりやすくなることもあります。
x = ["aaa", "bbb", "ccc"]
print(type(x))
print(x[0])
<class 'list'>
aaa
- 主な性質
- ミュータブル
- シーケンス
- イテラブル
- 主なメソッド
- append()
- pop()
辞書型(dict)
{}
(カーリーブラケット)で囲まれたデータが辞書型として定義されます。
key:valueの塊を1要素として扱い、keyにアクセスすることでvalueの値を参照したり、変更することができます。
主に処理に必要なデータ(要素)が多い場合に使用します。
それぞれの値をユニークなkeyで管理することによって、要素のインデックスを意識することなく、要素へアクセスすることができます。
x = {"a":"apple", "b":"banana", "c":"cherry"}
print(type(x))
print(x["a"])
<class 'dict'>
apple
- 主な性質
- ミュータブル
- イテラブル
- マッピング
- 主なメソッド
- keys()
- items()
まとめ
「データ型を制すればPythonを制す」
まさにこの通りで、データ型を理解することで圧倒的にエラーや構築時の無駄な処理が減りました。
特にリストや辞書を理解することでプログラムがどのように処理されているかを追えるようになり、Githubなどで公開されているpythonライブラリのDocs(説明書)を読むのが楽しくなりました。
シンプルが故に本当に理解しないといけない部分が見えないのがpythonであり、それが良いところでもある。
この記事で少しでもデータ型の理解が深まれば嬉しいです。
もしよろしければ***「いいね」***を頂けるとより多くの方にご覧いただけるため、ポチっとしていただけると幸いです。