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の後の0int()の引数として用いられます。

>>> e = ""
>>> int(e or 0)
0
>>> n = None
>>> int(n or 0)
0

なお、デフォルト値は以下のように任意の整数を指定できます。

>>> n = None
>>> int(n or -1)
-1

最後に

int()で文字列を整数データに変換しようとしたときに、よく遭遇するエラーと解決方法についてまとめてみました。文字列に「ピリオド」や「カンマ」が含まれているケースでは組み込み関数のfloat()filter()で簡単に解決できますが、任意の「単位」が含まれるケースでは正規表現が必要になります。

正規表現がはじめての場合は、難しく感じるかもしれませんが、使えるようになると非常に強力です。以下のような厚めの入門書には大抵掲載されていますので、ぜひご活用ください。