連載
» 2021年02月12日 05時00分 公開

[解決!Python]文字列が数字だけで構成されているかどうかを判定するには(isdecimal/isdigit/isnumeric/isasciiメソッド)解決!Python

isdecimalメソッドを使って、文字列が数字だけで構成されているかどうかを判定する方法を紹介。isdigit/isnumericメソッドとの違いも取り上げる。

[かわさきしんじ,Deep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「解決!Python」のインデックス

連載目次

# 文字列が半角10進数字のみで構成されているかどうかを判定する関数
def isascnum(s):
    return True if s.isdecimal() and s.isascii() else False

s1, s2, s3 = '123', '123', '123foo'

r1 = isascnum(s1)
r2 = isascnum(s2)
r3 = isascnum(s3)
print(f'{s1} isascnum: {r1}'# 123 isascnum: True
print(f'{s2} isascnum: {r2}'# 123 isascnum: False
print(f'{s3} isascnum: {r3}'# 123foo isascnum: False

# 文字列が10進数字のみで構成されているかどうかを判定
s1, s2, s3 = '123', '123', '123foo'

r1 = s1.isdecimal()
r2 = s2.isdecimal()  # 全角数字はTrueとなる
r3 = s3.isdecimal()
print(f'{s1} isdecimal: {r1}'# 123 isdecimal: True
print(f'{s2} isdecimal: {r2}'# 123 isdecimal: True
print(f'{s3} isdecimal: {r3}'# 123foo isdecimal: False

s1, s2 = '-1', '1.23'
r1 = s1.isdecimal()  # 符号が入っているとFalse
r2 = s2.isdecimal()  # 小数点が入っているとFalse
print(f'{s1} isdecimal: {r1}'# -1 isdecimal: False
print(f'{s2} isdecimal: {r2}'# 1.23 isdecimal: False

# isdecimal/isdigit/isnumericメソッドの違い
s = '123'  # 10進数字は全てTrue
r1 = s.isdecimal()
r2 = s.isdigit()
r3 = s.isnumeric()
print(f'{s} isdecimal: {r1}'# 123 isdecimal: True
print(f'{s} isdigit: {r2}'# 123 isdigit: True
print(f'{s} isnumeric: {r3}'# 123 isnumeric: True

s = '\u00b9\u00b2\u00b3'  # 上付き数字の1、2、3はisdigit/isnumericではTrue
r1 = s.isdecimal()
r2 = s.isdigit()
r3 = s.isnumeric()
print(f'{s} isdecimal: {r1}'# 123 isdecimal: False
print(f'{s} isdigit: {r2}'# 123 isdigit: True
print(f'{s} isnumeric: {r3}'# 123 isnumeric: True

s = '二億四千万'  # 漢数字などはisnumericでのみTrue
r1 = s.isdecimal()
r2 = s.isdigit()
r3 = s.isnumeric()
print(f'{s} isdecimal: {r1}'# 二億四千万 isdecimal: False
print(f'{s} isdigit: {r2}'# 二億四千万 isdigit: False
print(f'{s} isnumeric: {r3}'# 二億四千万 isnumeric: True


文字列が10進数字のみで構成されているかどうかを判定

 文字列のisdecimalメソッドを使うと、その文字列が10進数字のみで構成されているかどうかを判定できる。

 以下に例を示す。

s1, s2, s3 = '123', '123', '123foo'

r1 = s1.isdecimal()
r2 = s2.isdecimal()  # 全角数字はTrueとなる
r3 = s3.isdecimal()
print(f'{s1} isdecimal: {r1}'# 123 isdecimal: True
print(f'{s2} isdecimal: {r2}'# 123 isdecimal: True
print(f'{s3} isdecimal: {r3}'# 123foo isdecimal: False


 ただし、上記例を見ると分かるが、全角数字のみで構成される文字列'123'についてもisdecimalメソッドはTrueを返す。このメソッドは、UnicodeのGeneral_Categoryプロパティの値が'Nd'であるものを10進数字として判定するようになっているからだ(Unicode Consortiumが提供しているUnicodeData.txtファイル)の3番目のフィールドを参照)。これらの数字はint関数で整数値に変換可能でもある。

 このため、文字列が半角数字だけを含んでいるかどうかを知りたいときには、isasciiメソッドを組み合わせる必要がある。

s = '123'
if s.isdecimal() and s.isascii():
    print(f'{s} includes only ASCII digits')
else:
    print(f'{s} includes decimal characters')
# 出力結果:
# 123 include decimal characters


 これらを組み合わせて以下のような関数を定義してもよいだろう。

def isascnum(s):
    return True if s.isdecimal() and s.isascii() else False

s1, s2, s3 = '123', '123', '123foo'

r1 = isascnum(s1)
r2 = isascnum(s2)
r3 = isascnum(s3)
print(f'{s1} isascnum: {r1}'# 123 isascnum: True
print(f'{s2} isascnum: {r2}'# 123 isascnum: False
print(f'{s3} isascnum: {r3}'# 123foo isascnum: False


 注意点としては、isdecimalメソッドは符号や小数点を含んだ文字列に対してはFalseを返すことが挙げられる。

s1 = '-12'
s2 = '1.23'
r1, r2 = s1.isdecimal(), s2.isdecimal()
print(f'{s1} isdecimal: {r1}'# -12 isdecimal: False
print(f'{s2} isdecimal: {r2}'# 1.23 isdecimal: False


 符号や小数点を含んだ文字列を数値に変換できるかどうかを判定する方法については「[解決!Python]文字列が数値へ変換可能かどうかを判定するには(int/float関数の例外、re.fullmatch関数)」を参照されたい。

isdecimal/isdigit/isnumericメソッド

 通常は上で述べたisdecimalメソッドを使えば、おおよそ10進数字として扱われるものを判定できる。しかし、Pythonの文字列にはisdigitメソッドとisnumericメソッドの2つのメソッドがある。isdecimalメソッドを含むこれら3つのメソッドの違いを以下にまとめる。

メソッド 説明
isdecimalメソッド UnicodeのGeneral_Categoryプロパティの値がNdのものをTrueとする(UnicodeのNumeric_Typeプロパティの値がDecimalのものをTrueとする)
isdigitメソッド UnicodeのNumeric_Typeプロパティの値がDigit/DecimalのものをTrueとする
isnumeircメソッド UnicodeのNumeric_Typeプロパティの値がDigit/Decimal/NumericのものをTrueとする
isdecimal/isdigit/isnumericメソッドの違い

 なお、UnicodeのGeneral_Category=Ndである文字とNumeric_Type=Decimalである文字は同一といってよさそうであることから、上のisdecimalメソッドの説明にはその旨を記載してある(「UNICODE CHARACTER DATABASE」の「UCD File Format Invariants」項が始まる直前の段落には「the set of characters having General_Category=Nd will always be the same as the set of characters having NumericType=de」とある)。

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。