pythonで文字列が数値かどうかを判断する

morimotoです。

今回は数値変換(int())を行う前に、数値変換できる文字列なのかを検証してみましょうという記事です。

まず数値変換についてです。

>>> s1 = "12345"
>>> s2 = "abcde"
>>> int(s1)
12345
>>> int(s2)
Traceback (most recent call last):
  File "", line 1, in ?
ValueError: invalid literal for int(): abcde

s1は数値の文字列なので変換可能ですが、s2は当然数値ではないので変換は出来ません。

エラーを吐かれたほうが親切な場合も多いですが、煩わしいと思う方も居るかもしれません。

そこで、変換前に入力値が数値かどうかを判断してから数値を変換するメソッドを作ってみました。

数値検証用メソッド

# Validate functions
# 数値の文字列ならTrueです(Long型 30L とかは対象外)
def validates_number_of(value):
    return re.match(r'^(?![-+]0+$)[-+]?([1-9][0-9]*)?[0-9](\.[0-9]+)?$', '%s'%value) and True or False

# 整数値かどうかの検証
def validates_integer_of(value):
    return re.match(r'^(?![-+]0*$)[-+]?([1-9][0-9]*)?0?$', '%s'%value) and True or False

# 数値でintegerじゃなかったらfloatよね?(ちょっと手抜き)
def validates_float_of(value):
    return validates_number_of(value) and not validates_integer_of(value) or False

テスト

+--------------------++---------------------+----------------------+--------------------+
|               args || validates_number_of | validates_integer_of | validates_float_of |
+--------------------++---------------------+----------------------+--------------------+
|             123456 ||                True |                 True |              False |
|                  0 ||                True |                 True |              False |
|                 -9 ||                True |                 True |              False |
|                 +5 ||                True |                 True |              False |
|                 +9 ||                True |                 True |              False |
|             0.0000 ||                True |                False |               True |
|            1234.56 ||                True |                False |               True |
|            -123.45 ||                True |                False |               True |
|            +123.45 ||                True |                False |               True |
|             -0.123 ||                True |                False |               True |
|          123.00000 ||                True |                False |               True |
|          +00000000 ||               False |                False |              False |
|          -00000000 ||               False |                False |              False |
|                 +0 ||               False |                False |              False |
|                 -0 ||               False |                False |              False |
|             ABCDEF ||               False |                False |              False |
|               1+23 ||               False |                False |              False |
|               123- ||               False |                False |              False |
|              -.123 ||               False |                False |              False |
|               123. ||               False |                False |              False |
|              00012 ||               False |                False |              False |
|               .123 ||               False |                False |              False |
|              +0000 ||               False |                False |              False |
|              -0000 ||               False |                False |              False |
|           +0000.22 ||               False |                False |              False |
|                  + ||               False |                False |              False |
|                  - ||               False |                False |              False |
+--------------------++---------------------+----------------------+--------------------+

数値変換メソッド

上記検証用のメソッドを用いて作ります。

# 汚くて申し訳ない!
def to_int(value, default=None):
    (ret,) = validates_integer_of(value) and (int(value),) or \
            (validates_number_of(value) and (int(float(value)),) or (default,))
    return ret

テスト

+--------------------++--------+
|               args || to_int |
+--------------------++--------+
|             123456 || 123456 |
|                  0 ||      0 |
|                 -9 ||     -9 |
|                 +5 ||      5 |
|                 +9 ||      9 |
|             0.0000 ||      0 |
|            1234.56 ||   1234 |
|            -123.45 ||   -123 |
|            +123.45 ||    123 |
|             -0.123 ||      0 |
|          123.00000 ||    123 |
|          +00000000 ||   None |
|          -00000000 ||   None |
|                 +0 ||   None |
|                 -0 ||   None |
|             ABCDEF ||   None |
|               1+23 ||   None |
|               123- ||   None |
|              -.123 ||   None |
|               123. ||   None |
|              00012 ||   None |
|               .123 ||   None |
|              +0000 ||   None |
|              -0000 ||   None |
|           +0000.22 ||   None |
|                  + ||   None |
|                  - ||   None |
+--------------------++--------+

入力値がintegerでなかったらNoneを返すメソッドができました。

s = "123o123"
i = to_int(s)
if i:
    print "数値ですよ"
else:
    print "数値じゃないよ"

みたいな使い方もできるのかな?

以上、morimotoでした。

Categorized: Python

Comments are closed.