一覧PG-02-1 · 型と変換

Pythonの型変換と変換エラー

文字列の番号と個数を使い、変換前後の演算を確認します。変換に失敗したときの変数、Noneと0、真偽の判定、関数に渡す型まで順に試します。

説明

Pythonの値にはint、float、strなどの型があり、型によって同じ演算子の動作が変わります。数字の表記を保つ文字列と、数量として計算する数値は目的が違います。

文字列の番号と個数を使い、変換前後の演算を確認します。変換に失敗したときの変数、Noneと0、真偽の判定、関数に渡す型まで順に試します。

1同じ見た目でも型が違う

番号の表記"08"、整数8、浮動小数点数8.0を用意します。

code = '08'; count = 8; ratio = 8.0文字列・整数・floatを用意; [(repr(x), type(x).__name__) for x in (code, count, ratio)]表記と型の一覧

文字列は先頭の0を保持します。整数やfloatは数値であり、8と8.0は等しい値として比較できても型は異なります。番号として必要な表記を数量へ変換すると、先頭の0は残りません。

2型によって+と*の動作が変わる

同じ2を使い、文字列の反復、整数の乗算、文字列の連結を並べます。

print(code * 2, count * 2, code + '2')反復・乗算・連結; print(count + ratio, type(count + ratio).__name__)数値の混合演算

文字列は0808と082、数値は16です。整数とfloatを加算した結果16.0はfloatになります。文字列と数値の混合を何でも自動変換するわけではありません。

3明示的に整数へ変換する

個数として計算するため、文字列をintへ変換します。

converted = int(code)文字列を整数へ変換; print(converted + 2, code, str(converted))演算・元の値・再文字列化

計算結果は10、元のcodeは08のままです。整数8をstrへ戻しても8という表記になり、元の先頭0までは復元しません。変換が元の表記を完全に保つとは限りません。

4変換に失敗した代入

convertedへ3.5という文字列を整数変換して代入しようとします。

converted = int('3.5')整数ではない表記の変換

intはこの文字列を整数として解釈できずValueErrorになります。右辺で例外が発生したため、左辺への代入まで進んでいません。

5失敗後に残る値と小数の扱い

convertedを確認し、小数として読み込んだ後の整数変換も試します。

print(converted)代入失敗後の値; print(float('3.5'), int(3.5), int(-3.5))小数の解析と0方向の変換

convertedは以前の8を保持しています。floatなら3.5を読めますが、floatからintへの変換は0方向へ小数部分を落とすため3と-3になります。四捨五入ではありません。

6大きな整数をfloatへ変換する

Pythonの整数はこの値を正確に持てますが、通常のfloatの有効精度には限界があります。隣り合う大きな整数を変換します。

a = 2**53; b = a + 1隣り合う整数; print(a == b, float(a) == float(b))整数とfloatで比較; print(int(float(b)) == b)往復変換で戻るか確認

整数では異なる二値が、floatでは同じ値になります。floatをintへ戻しても失われた差は回復しません。通常のfloatは二進の有効桁が53ビットで、この大きさではすべての連続整数を表現できません。

7Noneと正当な0を扱う

在庫0と未登録を同じ扱いにしないように、辞書から得る値と真偽を調べます。

stock = {'pen': 0}0を持つ登録済み商品; values = [stock.get('pen'), stock.get('book'), '', 'False', False]0・不在・文字列・真偽値; [(repr(x), x is None, bool(x)) for x in values]値の不在と真偽を別々に確認

0、None、空文字列、Falseはいずれも偽として判定されますが、同じ値ではありません。文字列'False'は空でないので真です。未登録を調べる条件にはis Noneを使い、boolの結果だけで決めません。

8同じ関数に異なる型を渡す

引数に2を掛ける関数を定義します。引数の型を固定する処理は書いていません。

def twice(value):値を受け取る関数 return value * 2型に応じた*の結果

演算は呼び出した時点の値の型に応じて実行されます。関数を一度定義しただけで、引数がすべて同じ型へ変わるわけではありません。

9成功する型と失敗する型

数値、文字列、リストで呼び出してから、Noneでも呼び出します。

print(twice(3), twice('3'), twice([3]))型別の演算結果; twice(None)乗算に対応しない値

数値は6、文字列は33、リストは[3, 3]です。Noneでは乗算できずTypeErrorになります。ValueErrorは解釈できない表記、今回のTypeErrorは対応しない型の操作という違いがあります。

まとめ

変換が成功しても表記や精度が失われる場合があります。

0、None、文字列のFalseなどを、値の意味と型に応じて扱います。

操作履歴と解説を振り返れます。

Python 3

1
code = '08'; count = 8; ratio = 8.0; [(repr(x), type(x).__name__) for x in (code, count, ratio)]
[("'08'", 'str'), ('8', 'int'), ('8.0', 'float')]
2
print(code * 2, count * 2, code + '2'); print(count + ratio, type(count + ratio).__name__)
0808 16 082
16.0 float
3
converted = int(code); print(converted + 2, code, str(converted))
10 08 8
4
converted = int('3.5')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '3.5'
5
print(converted); print(float('3.5'), int(3.5), int(-3.5))
8
3.5 3 -3
6
a = 2**53; b = a + 1; print(a == b, float(a) == float(b)); print(int(float(b)) == b)
False True
False
7
stock = {'pen': 0}; values = [stock.get('pen'), stock.get('book'), '', 'False', False]; [(repr(x), x is None, bool(x)) for x in values]
[('0', False, False), ('None', True, False), ("''", False, False), ("'False'", False, True), ('False', False, False)]
8
def twice(value): return value * 2
9
print(twice(3), twice('3'), twice([3])); twice(None)
6 33 [3, 3]
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "<console>", line 2, in twice
TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'

演習完了