Pythonではint()
やfloat()
を用いることで「数値の文字列」を数値のデータ(int型やfloat型)に変換できます。
float()
は実数を対象としていますが、int()
は整数に限定されるので、思わぬところでエラーに遭遇することがあります。今回はそのようなint()でエラーになるケースについて考えます。
int()
はPythonの組み込み関数 であり、以下のように「整数の文字列」を引数に指定すると「int型のデータ」に変換できます。
>>> int("123")
123
>>> type(int("123"))
<class 'int'>
整数の文字列は全角文字で入力しても、以下のように変換してくれます。
>>> int("123")
123
また、整数部分の前に0
や符号(+
, -
)があっても正しく変換します。
>>> int("-0123")
-123
しかし、ピリオドやカンマなど余計な文字を含んでいるとエラーになります。今回はこのようにint()
で文字列を変換するときによくエラーになるケースと解決方法をまとめてみました。
本記事の目次
ケース1:小数点数の文字列
ピリオド(.
)を含む小数点数の文字列をint()
で変換しようとすると以下のようにエラーになります。
>>> int("123.45")
Traceback (most recent call last): File "
", line 1, in ValueError: invalid literal for int() with base 10: '123.45'
この場合は組み込み関数の「float( ) 」で小数点数の文字列を小数点数に変換してから、小数点数をint()
で整数に変換します。
>>> int(float("123.45"))
123
float()
とint()
の変換は、以下のように実行されます。小数点数をint()
で変換すると整数部だけになります(つまり、小数点以下は切り捨てされます)。
>>> float("123.45")
123.45
>>> int(123.45)
123
ケース2:千の位ごとにカンマがある文字列
千の位ごとの桁区切りにカンマ(,
)がある整数の文字列をint()
で変換しようとすると以下のようにエラーになります。
>>> int("123,000,000")
Traceback (most recent call last): File "
", line 1, in ValueError: invalid literal for int() with base 10: '123,000,000'
この場合は、以下のように文字列メソッドの「str.replace( ) 」を用いてカンマを取り除いてから、int()
で変換します。
>>> int("123,000,000".replace(",",""))
123000000
replace(検索する部分文字列, 置換する文字列)
で引数をそれぞれ","
と""
(空文字)を指定すると文字列からカンマを取り除けます。
>>> "123,000,000".replace(",","")
'123000000'
ケース3:単位を含む文字列
整数の文字列にkmやkgなどの単位が付いている場合、そのままint()
で変換しようとすると以下のようにエラーになります。
>>> int("2500km")
Traceback (most recent call last): File "
", line 1, in ValueError: invalid literal for int() with base 10: '2500km'
この場合は、以下のように数字の文字だけを組み込み関数の「filter( ) 」を用いて取得し、文字列メソッドの「str.join( ) 」で結合してからint()
で変換します。
>>> int("".join(filter(str.isdigit, "2500km")))
2500
filter()
の1つ目の引数に、文字が数字の時にTrue
を返す文字列メソッド「str.isdigit() 」を指定します。これにより、以下のように数字の文字だけを取得できます。
>>> list(filter(str.isdigit, "2500km"))
['2', '5', '0', '0']
>>> "".join(['2', '5', '0', '0'])
'2500'
str.isdigit()
は以下のように数字の文字に対してTrue
を返します。上記のように引数に指定するときは、かっこを除いてstr.isdigit
だけ指定します。
>>> str.isdigit("2")
True
>>> str.isdigit("0")
True
>>> str.isdigit("k")
False
数値の部分が小数点数の場合
「2500.567km
」のように数値の部分が小数点数の場合は、正規表現を使います。
>>> import re
>>> int(float(re.findall(r"\d+\.\d+", "2500.567km")[0]))
2500
標準の「reモジュール 」のfindall()
を用いて小数点数を表す正規表現のパターン\d+\.\d+
にマッチする文字列のリストを取得できます。
>>> import re
>>> re.findall(r"\d+\.\d+", "2500.567km")
['2500.567']
なお、単位がアルファベット文字だけならば、以下のようにfilter()
を使って書くこともできますが、少し煩雑になります。
>>> int(float("".join(filter(lambda c: not str.isalpha(c), "2500.567km"))))
2500
さらに、「-40.52度
」のように符号(+
,-
)が付いている場合は、正規表現のパターンに以下のように[-+]?
を前に加えます。
>>> import re
>>> int(float(re.findall(r"[-+]?\d+\.\d+", "-40.52度")[0]))
-40
このパターンを用いると、以下のように符号も一緒に取得できるのが確認できます。
>>> import re
>>> re.findall(r"[-+]?\d+\.\d+", "-40.52度")
['-40.52']
数値の部分が整数か小数点数の場合
数値の部分が整数、小数点数のどちらでも変換できるようにするには正規表現のパターンのピリオド.
の後ろに「0個か1個」を表す?
を加えます。
以下のようなパターンを用いれば、さらに符号があっても変換できるようになります。
>>> import re
>>> int(float(re.findall(r"[-+]?\d+\.?\d+", "-40度")[0]))
-40
>>> int(float(re.findall(r"[-+]?\d+\.?\d+", "-40.52度")[0]))
-40
>>> int(float(re.findall(r"[-+]?\d+\.?\d+", "+40度")[0]))
40
>>> int(float(re.findall(r"[-+]?\d+\.?\d+", "40度")[0]))
40
空文字やNone
空文字やNoneをint()
で変換しようとすると以下のようにエラーになります。
>>> int("")
Traceback (most recent call last): File "
", line 1, in ValueError: invalid literal for int() with base 10: '' >>> int(None)
Traceback (most recent call last): File "
", line 1, in TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'
この場合は、以下のようにor
を用いてデフォルト値を指定します。空文字やNoneはブール演算ではFalseに見なされるので、or
の後の0
がint()
の引数として用いられます。
>>> e = ""
>>> int(e or 0)
0
>>> n = None
>>> int(n or 0)
0
なお、デフォルト値は以下のように任意の整数を指定できます。
>>> n = None
>>> int(n or -1)
-1
最後に
int()
で文字列を整数データに変換しようとしたときに、よく遭遇するエラーと解決方法についてまとめてみました。文字列に「ピリオド」や「カンマ」が含まれているケースでは組み込み関数のfloat()
やfilter()
で簡単に解決できますが、任意の「単位」が含まれるケースでは正規表現が必要になります。
正規表現がはじめての場合は、難しく感じるかもしれませんが、使えるようになると非常に強力です。以下のような厚めの入門書には大抵掲載されていますので、ぜひご活用ください。