Pythonで文字列が数値として表現できるかどうかを確認するための最善の方法は何ですか?
私が現在持っている機能は:
def is_number(s):
try:
float(s)
return True
except ValueError:
return False
これは、醜くて遅いだけでなく、不格好なようです。しかし、メイン関数でfloat
を呼び出すのはさらに悪いので、もっと良い方法は見つけられませんでした。
それは、醜くて遅いだけではありません
私は両方とも争います。
正規表現や他の文字列の解析は、より曖昧で遅くなります。
私は、何かが上記よりも速くなることができるかどうかわからない。関数を呼び出して戻ります。 Try/Catchを使用しても、ほとんどのオーバーヘッドは発生しません。最も一般的な例外は、スタックフレームを広範囲に検索しなくても発生するためです。
問題は、どの数値変換関数にも2種類の結果があることです。
C(例として)は、これを回避するためのいくつかの方法があります。 Pythonはそれを明確かつ明示的にレイアウトしています。
これを行うためのコードは完璧だと思います。
浮動小数点数の代わりに(正の符号なし)整数の解析を探している場合は、文字列オブジェクトに isdigit()
関数を使用できます。
>>> a = "03523"
>>> a.isdigit()
True
>>> b = "963spam"
>>> b.isdigit()
False
Unicode文字列に関するものもあります。 Unicode - decimal/decimal にはあまり精通していません。
TL; DR 最良の解決策はs.replace('.','',1).isdigit()
です
ベンチマーク さまざまなアプローチの比較
def is_number_tryexcept(s):
""" Returns True is string is a number. """
try:
float(s)
return True
except ValueError:
return False
import re
def is_number_regex(s):
""" Returns True is string is a number. """
if re.match("^\d+?\.\d+?$", s) is None:
return s.isdigit()
return True
def is_number_repl_isdigit(s):
""" Returns True is string is a number. """
return s.replace('.','',1).isdigit()
文字列が数値ではない場合、except-blockは非常に遅いです。しかしもっと重要なことに、try-exceptメソッドは科学的表記法を正しく扱う唯一のアプローチです。
funcs = [
is_number_tryexcept,
is_number_regex,
is_number_repl_isdigit
]
a_float = '.1234'
print('Float notation ".1234" is not supported by:')
for f in funcs:
if not f(a_float):
print('\t -', f.__name__)
浮動小数点表記「.1234」は、以下ではサポートされていません。
- is_number_regex
scientific1 = '1.000000e+50'
scientific2 = '1e50'
print('Scientific notation "1.000000e+50" is not supported by:')
for f in funcs:
if not f(scientific1):
print('\t -', f.__name__)
print('Scientific notation "1e50" is not supported by:')
for f in funcs:
if not f(scientific2):
print('\t -', f.__name__)
科学表記 "1.000000e + 50"は、以下によってサポートされていません。
- is_number_regex
- is_number_repl_isdigit
科学表記「1e50」は、以下によってサポートされていません。
- is_number_regex
- is_number_repl_isdigit
import timeit
test_cases = ['1.12345', '1.12.345', 'abc12345', '12345']
times_n = {f.__name__:[] for f in funcs}
for t in test_cases:
for f in funcs:
f = f.__name__
times_n[f].append(min(timeit.Timer('%s(t)' %f,
'from __main__ import %s, t' %f)
.repeat(repeat=3, number=1000000)))
以下の機能がテストされた場所
from re import match as re_match
from re import compile as re_compile
def is_number_tryexcept(s):
""" Returns True is string is a number. """
try:
float(s)
return True
except ValueError:
return False
def is_number_regex(s):
""" Returns True is string is a number. """
if re_match("^\d+?\.\d+?$", s) is None:
return s.isdigit()
return True
comp = re_compile("^\d+?\.\d+?$")
def compiled_regex(s):
""" Returns True is string is a number. """
if comp.match(s) is None:
return s.isdigit()
return True
def is_number_repl_isdigit(s):
""" Returns True is string is a number. """
return s.replace('.','',1).isdigit()
考慮しなければならない可能性がある例外が1つあります。文字列 'NaN'です。
Is_numberが 'NaN'に対してFALSEを返すようにしたい場合、Pythonはそれを数ではない数の表現に変換するので機能しません(アイデンティティの問題について話してください)
>>> float('NaN')
nan
さもなければ、私が実際に私が今広く使用しているコードの部分をありがとうございます。 :)
G.
これはどう:
'3.14'.replace('.','',1).isdigit()
これは、 '。'が1つあるかない場合にのみtrueを返します。数字のストリングで。
'3.14.5'.replace('.','',1).isdigit()
falseを返します
編集:ちょうど別のコメントを見た... 他の場合には.replace(badstuff,'',maxnum_badstuff)
を追加することができます。もしあなたがsaltを渡していて、任意の調味料ではないなら(ref: xkcd#974 )これはうまくいくでしょう:P
Alfeがfloatをチェックする必要はないと指摘した後に更新されました。
def is_number(s):
try:
complex(s) # for int, long, float and complex
except ValueError:
return False
return True
以前に言われました:あなたが同じくfloatで表されることができない複素数(例えば1 + 2i)をチェックする必要があるかもしれないいくつかのまれなケースです:
def is_number(s):
try:
float(s) # for int, long and float
except ValueError:
try:
complex(s) # for complex
except ValueError:
return False
return True
これは、醜くて遅いだけでなく、不格好なようです。
慣れるまでに時間がかかるかもしれませんが、これがPythonicのやり方です。すでに指摘したように、代替案はもっと悪いです。しかし、このようにすることにはもう1つの利点があります。それは多態性です。
アヒルのタイピングの背後にある中心的な考え方は、「アヒルのように歩き、話すならば、それはアヒルだ」ということです。何かをfloatに変換できるかどうかを判断する方法を変更できるように、stringをサブクラス化する必要があると判断した場合はどうしますか?あるいは、他のオブジェクトを完全にテストすることにした場合はどうなりますか?上記のコードを変更しなくても、これらのことを実行できます。
他の言語はインターフェースを使用することによってこれらの問題を解決します。どの解決策が別のスレッドに適しているかについての分析は省きます。ただし、重要なのは、Pythonは方程式のアヒルタイピング側にあるということです。Pythonで多くのプログラミングを行う予定であれば、おそらくこのような構文に慣れる必要があるでしょう(ただし、それは意味ではありません)。あなたはもちろんそれを好む必要があります。
考慮すべきもう1つのことがあります。Pythonは、他の多くの言語と比較して例外のスローとキャッチが非常に高速です(たとえば、.Netよりも30倍高速です)。一体、言語自体も例外をスローして、例外ではない通常のプログラム条件を伝達します(forループを使用するたびに)。したがって、重大な問題に気付くまでは、このコードのパフォーマンス面についてあまり気にする必要はありません。
int
にはこれを使います。
>>> "1221323".isdigit()
True
しかしfloat
にはいくつかのトリックが必要です;-)。すべての浮動小数点数は1つの点を持ちます...
>>> "12.34".isdigit()
False
>>> "12.34".replace('.','',1).isdigit()
True
>>> "12.3.4".replace('.','',1).isdigit()
False
負の数の場合もlstrip()
を追加するだけです。
>>> '-12'.lstrip('-')
'12'
そして今、私たちは普遍的な方法を手に入れます。
>>> '-12.34'.lstrip('-').replace('.','',1).isdigit()
True
>>> '.-234'.lstrip('-').replace('.','',1).isdigit()
False
C#には、スカラー値の解析を処理する2つの異なる関数があります。
float.parse():
def parse(string):
try:
return float(string)
except Exception:
throw TypeError
注:なぜ例外をTypeErrorに変更したのか疑問に思う場合は、 ここにドキュメントがあります 。
float.try_parse():
def try_parse(string, fail=None):
try:
return float(string)
except Exception:
return fail;
注:それでも値型であるため、ブール値の「False」を返したくはありません。失敗を示すものはありません。もちろん、違うものが必要な場合は、failパラメーターを任意の値に変更できます。
Parse()とtry_parse()を含むようにfloatを拡張するには、これらのメソッドを追加するためにfloatクラスをモンキーパッチする必要があります。
既存の関数を尊重したい場合は、コードは次のようになります。
def monkey_patch():
if(!hasattr(float, 'parse')):
float.parse = parse
if(!hasattr(float, 'try_parse')):
float.try_parse = try_parse
SideNote:私は個人的にモンキーパンチングと呼ぶことを好みます。なぜなら、私はこれをするとYMMVをするときに言語を悪用しているように感じるからです。
使用法:
float.parse('giggity') // throws TypeException
float.parse('54.3') // returns the scalar value 54.3
float.tryParse('twank') // returns None
float.tryParse('32.2') // returns the scalar value 32.2
そして偉大なSage PythonasはSharpisusに言った、「あなたができることなら何でも私はもっとよくできます。私はあなたよりももっとよくできます」
数字以外の文字列の場合、try: except:
は実際には正規表現より遅くなります。有効な数値の文字列の場合、正規表現は遅くなります。したがって、適切な方法は入力内容によって異なります。
自分がパフォーマンスの限界にあるとわかった場合は、 fastnumbers という新しいサードパーティ製モジュールを使用して、 isfloat という関数を使用できます。完全な開示、私は作者です。その結果を以下のタイミングに含めました。
from __future__ import print_function
import timeit
prep_base = '''\
x = 'invalid'
y = '5402'
z = '4.754e3'
'''
prep_try_method = '''\
def is_number_try(val):
try:
float(val)
return True
except ValueError:
return False
'''
prep_re_method = '''\
import re
float_match = re.compile(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$').match
def is_number_re(val):
return bool(float_match(val))
'''
fn_method = '''\
from fastnumbers import isfloat
'''
print('Try with non-number strings', timeit.timeit('is_number_try(x)',
prep_base + prep_try_method), 'seconds')
print('Try with integer strings', timeit.timeit('is_number_try(y)',
prep_base + prep_try_method), 'seconds')
print('Try with float strings', timeit.timeit('is_number_try(z)',
prep_base + prep_try_method), 'seconds')
print()
print('Regex with non-number strings', timeit.timeit('is_number_re(x)',
prep_base + prep_re_method), 'seconds')
print('Regex with integer strings', timeit.timeit('is_number_re(y)',
prep_base + prep_re_method), 'seconds')
print('Regex with float strings', timeit.timeit('is_number_re(z)',
prep_base + prep_re_method), 'seconds')
print()
print('fastnumbers with non-number strings', timeit.timeit('isfloat(x)',
prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with integer strings', timeit.timeit('isfloat(y)',
prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with float strings', timeit.timeit('isfloat(z)',
prep_base + 'from fastnumbers import isfloat'), 'seconds')
print()
Try with non-number strings 2.39108395576 seconds
Try with integer strings 0.375686168671 seconds
Try with float strings 0.369210958481 seconds
Regex with non-number strings 0.748660802841 seconds
Regex with integer strings 1.02021503448 seconds
Regex with float strings 1.08564686775 seconds
fastnumbers with non-number strings 0.174362897873 seconds
fastnumbers with integer strings 0.179651021957 seconds
fastnumbers with float strings 0.20222902298 seconds
ご覧のように
try: except:
は数値入力では高速でしたが、無効な入力では非常に低速でしたfastnumbers
が勝ちます私はこれが特に古いことを知っていますが、私はこれを見つける誰にとっても非常に貴重であるかもしれない最も高い投票された答えから抜けている情報をカバーすると私が信じる答えを加えます:
あなたが入力を受け入れる必要がある場合は、以下の方法のそれぞれについて、それらをカウントで接続します。 (0〜255などではなく、整数のボーカル定義を使用していると仮定します。)
x.isdigit()
は、xが整数かどうかを調べるのに適しています。
x.replace('-','').isdigit()
は、xが負であるかどうかを確認するのに適しています(最初の位置にチェックインします)。
x.replace('.','').isdigit()
は、xが10進数であるかどうかを確認するのに適しています。
x.replace(':','').isdigit()
は、xが比率であるかどうかを確認するのに適しています。
x.replace('/','',1).isdigit()
は、xが小数であるかどうかを確認するのに適しています。
あなたはUnicode文字列を使用することができます、彼らはあなたが望むことをする方法を持っています:
>>> s = u"345"
>>> s.isnumeric()
True
または
>>> s = "345"
>>> u = unicode(s)
>>> u.isnumeric()
True
Float()はそのためだけのものなので、floatにキャストしてValueErrorをキャッチするのがおそらく最速の方法です。文字列の解析を必要とするもの(regexなど)は、この操作に合わせて調整されていないため、おそらく遅くなります。私の0.02ドル。
どの方法が最速かを見たかったのです。全体的に最良で最も一貫した結果がcheck_replace
関数によって与えられました。最も速い結果はcheck_exception
関数によって与えられました、しかし例外が発生しなかった場合だけ - それはそのコードが最も効率的であることを意味します、しかし例外を投げることのオーバーヘッドはかなり大きいです。
成功したキャストをチェックすることが正確な唯一の方法であることに注意してください。例えば、これはcheck_exception
で動作しますが、他の2つのテスト関数は有効なfloatに対してFalseを返します。
huge_number = float('1e+100')
これがベンチマークコードです。
import time, re, random, string
ITERATIONS = 10000000
class Timer:
def __enter__(self):
self.start = time.clock()
return self
def __exit__(self, *args):
self.end = time.clock()
self.interval = self.end - self.start
def check_regexp(x):
return re.compile("^\d*\.?\d*$").match(x) is not None
def check_replace(x):
return x.replace('.','',1).isdigit()
def check_exception(s):
try:
float(s)
return True
except ValueError:
return False
to_check = [check_regexp, check_replace, check_exception]
print('preparing data...')
good_numbers = [
str(random.random() / random.random())
for x in range(ITERATIONS)]
bad_numbers = ['.' + x for x in good_numbers]
strings = [
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randint(1,10)))
for x in range(ITERATIONS)]
print('running test...')
for func in to_check:
with Timer() as t:
for x in good_numbers:
res = func(x)
print('%s with good floats: %s' % (func.__name__, t.interval))
with Timer() as t:
for x in bad_numbers:
res = func(x)
print('%s with bad floats: %s' % (func.__name__, t.interval))
with Timer() as t:
for x in strings:
res = func(x)
print('%s with strings: %s' % (func.__name__, t.interval))
これが2017年のMacBook Pro 13でのPython 2.7.10の結果です。
check_regexp with good floats: 12.688639
check_regexp with bad floats: 11.624862
check_regexp with strings: 11.349414
check_replace with good floats: 4.419841
check_replace with bad floats: 4.294909
check_replace with strings: 4.086358
check_exception with good floats: 3.276668
check_exception with bad floats: 13.843092
check_exception with strings: 15.786169
これが2017年のMacBook Pro 13でのPython 3.6.5の結果です。
check_regexp with good floats: 13.472906000000009
check_regexp with bad floats: 12.977665000000016
check_regexp with strings: 12.417542999999995
check_replace with good floats: 6.011045999999993
check_replace with bad floats: 4.849356
check_replace with strings: 4.282754000000011
check_exception with good floats: 6.039081999999979
check_exception with bad floats: 9.322753000000006
check_exception with strings: 9.952595000000002
これは2017 MacBook Pro 13でのPyPy 2.7.13の結果です。
check_regexp with good floats: 2.693217
check_regexp with bad floats: 2.744819
check_regexp with strings: 2.532414
check_replace with good floats: 0.604367
check_replace with bad floats: 0.538169
check_replace with strings: 0.598664
check_exception with good floats: 1.944103
check_exception with bad floats: 2.449182
check_exception with strings: 2.200056
この答えは、文字列が以下のものであることを見つけるための例を含む機能を有するステップバイステップガイドを提供します。
str.isdigit()
を使って、与えられた文字列が正の数整数)かどうかを調べることができます。
サンプル結果:
# For digit
>>> '1'.isdigit()
True
>>> '1'.isalpha()
False
文字列が負の数数値または浮動小数点数)の場合、str.isdigit()
はFalse
を返します。次に例を示します。
# returns `False` for float
>>> '123.3'.isdigit()
False
# returns `False` for negative number
>>> '-123'.isdigit()
False
を負の整数および float
もチェックしたい場合は、カスタム関数を作成して次のようにチェックします。
def is_number(n):
try:
float(n) # Type-casting the string to `float`.
# If string is not a valid `float`,
# it'll raise `ValueError` exception
except ValueError:
return False
return True
サンプル実行:
>>> is_number('123') # positive integer number
True
>>> is_number('123.4') # positive float number
True
>>> is_number('-123') # negative integer number
True
>>> is_number('-123.4') # negative `float` number
True
>>> is_number('abc') # `False` for "some random" string
False
Pythonではそれが数値ではないことを表す有効な浮動小数点数であるため、上記の関数は "NAN"(数値ではない)文字列に対してTrue
を返します。例えば:
>>> is_number('NaN')
True
番号が "NaN"であるかどうかを確認するには、 math.isnan()
を使用します。
>>> import math
>>> nan_num = float('nan')
>>> math.isnan(nan_num)
True
これをチェックするために追加のライブラリをインポートしたくない場合は、==
を使用してそれ自身と比較することで単純にチェックすることができます。 False
floatがそれ自身と比較されると、Pythonはnan
を返します。例えば:
# `nan_num` variable is taken from above example
>>> nan_num == nan_num
False
したがって、上記のfunction is_number
は、"NaN"
に対してFalse
を返すように更新できます。
def is_number(n):
is_number = True
try:
num = float(n)
# check for "nan" floats
is_number = num == num # or use `math.isnan(num)`
except ValueError:
is_number = False
return is_number
サンプル実行:
>>> is_number('Nan') # not a number "Nan" string
False
>>> is_number('nan') # not a number string "nan" with all lower cased
False
>>> is_number('123') # positive integer
True
>>> is_number('-123') # negative integer
True
>>> is_number('-1.12') # negative `float`
True
>>> is_number('abc') # "some random" string
False
PS:数値の種類に応じた各チェックの各操作には、追加のオーバーヘッドが伴います。要件に合ったis_number
関数のバージョンを選択してください。
あなたは文字列に数字があるとしましょう。
if str.isdigit():
returns TRUE or FALSE
そうでなければ、あなたのメソッドは文字列中の数字の出現を見つけるのにとてもうまくいきます。
つまり、Nan、無限大、複素数をチェックすると(iではなく、j、つまり1 + 2jで指定されるように見えます)、
def is_number(s):
try:
n=str(float(s))
if n == "nan" or n=="inf" or n=="-inf" : return False
except ValueError:
try:
complex(s) # for complex
except ValueError:
return False
return True
あなたのコードは私にはよく見えます。
おそらく、例外を使用しているためにコードが「不格好」だと思う? Pythonプログラマは、パフォーマンスが低下するため、コードの読みやすさを向上させる場合は、例外を自由に使用する傾向があります。
文字列が基本型(float、int、str、bool)にキャストされるかどうかを判断する必要がありました。インターネット上で何も見つけられなかった後、私はこれを作成しました:
def str_to_type (s):
""" Get possible cast type for a string
Parameters
----------
s : string
Returns
-------
float,int,str,bool : type
Depending on what it can be cast to
"""
try:
f = float(s)
if "." not in s:
return int
return float
except ValueError:
value = s.upper()
if value == "TRUE" or value == "FALSE":
return bool
return type(s)
例
str_to_type("true") # bool
str_to_type("6.0") # float
str_to_type("6") # int
str_to_type("6abc") # str
str_to_type(u"6abc") # unicode
あなたはタイプを捉えて使うことができます
s = "6.0"
type_ = str_to_type(s) # float
f = type_(s)
スピードテストをしました。文字列がlikelyである場合、try/except戦略が可能な限り高速であるとしましょう。 ありそうにない数字になるおよび興味がある整数チェック、テストする価値がある(isdigitと見出し '-') 。浮動小数点数を確認したい場合は、エスケープなしのtry/exceptコードを使用する必要があります。
入力は次のようになります。
a="50"
b=50
c=50.1
d="50.1"
この関数の入力はすべてです。
与えられた変数が数値かどうかを調べます。数値ストリングは、オプションの符号、任意の桁数、オプションの小数部、およびオプションの指数部で構成されています。したがって、+ 0123.45e6は有効な数値です。 16進数(例:0xf4c3b00c)およびバイナリ(例:0b10100111001)表記は許可されていません。
is_numeric function
import ast
import numbers
def is_numeric(obj):
if isinstance(obj, numbers.Number):
return True
Elif isinstance(obj, str):
nodes = list(ast.walk(ast.parse(obj)))[1:]
if not isinstance(nodes[0], ast.Expr):
return False
if not isinstance(nodes[-1], ast.Num):
return False
nodes = nodes[1:-1]
for i in range(len(nodes)):
#if used + or - in digit :
if i % 2 == 0:
if not isinstance(nodes[i], ast.UnaryOp):
return False
else:
if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
return False
return True
else:
return False
テスト:
>>> is_numeric("54")
True
>>> is_numeric("54.545")
True
>>> is_numeric("0x45")
True
is_float function
与えられた変数がfloatかどうかを調べます。 float文字列は、オプションの符号、任意の桁数、...からなります。
import ast
def is_float(obj):
if isinstance(obj, float):
return True
if isinstance(obj, int):
return False
Elif isinstance(obj, str):
nodes = list(ast.walk(ast.parse(obj)))[1:]
if not isinstance(nodes[0], ast.Expr):
return False
if not isinstance(nodes[-1], ast.Num):
return False
if not isinstance(nodes[-1].n, float):
return False
nodes = nodes[1:-1]
for i in range(len(nodes)):
if i % 2 == 0:
if not isinstance(nodes[i], ast.UnaryOp):
return False
else:
if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
return False
return True
else:
return False
テスト:
>>> is_float("5.4")
True
>>> is_float("5")
False
>>> is_float(5)
False
>>> is_float("5")
False
>>> is_float("+5.4")
True
ast とは何ですか?
str.isdigit() methodを使用してください。
>>> a=454
>>> a.isdigit()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'isdigit'
>>> a="454"
>>> a.isdigit()
True
int値を検出します。
>>> isinstance("54", int)
False
>>> isinstance(54, int)
True
>>>
フロートを検出:
>>> isinstance("45.1", float)
False
>>> isinstance(45.1, float)
True
RyanNは示唆している
NaNとInfに対してFalseを返したい場合は、lineをx = float(s)に変更します。 (x == x)と(x - 1!= x)を返します。これはInfとNaNを除くすべての浮動小数点数に対してTrueを返すはずです。
十分な大きさの浮動小数点数の場合、x-1 == x
はtrueを返します。たとえば、2.0**54 - 1 == 2.0**54
私はあなたが言及した関数も使用しました、しかしすぐに私は "Nan"、 "Inf"などの文字列とそのバリエーションが数として考慮されることに気付きます。それで私はあなたがあなたの関数の改良版を提案します、それはそれらのタイプの入力で偽を返し、そして "1e3"の変種を失敗しないでしょう:
def is_float(text):
try:
float(text)
# check for nan/infinity etc.
if text.isalpha():
return False
return True
except ValueError:
return False
TrueとFalseよりも有用な値を返すことで、例外の手法を便利な方法で一般化できます。例えば、この関数は文字列に丸引用符を付けますが、数字だけを残します。これは、私がRのためにいくつかの変数を定義するために素早くて汚いフィルタに必要なものです
import sys
def fix_quotes(s):
try:
float(s)
return s
except ValueError:
return '"{0}"'.format(s)
for line in sys.stdin:
input = line.split()
print input[0], '<- c(', ','.join(fix_quotes(c) for c in input[1:]), ')'
これを試して。
def is_number(var):
try:
if var == int(var):
return True
except Exception:
return False
ユーザーヘルパー機能:
def if_ok(fn, string):
try:
return fn(string)
except Exception as e:
return None
それから
if_ok(int, my_str) or if_ok(float, my_str) or if_ok(complex, my_str)
is_number = lambda s: any([if_ok(fn, s) for fn in (int, float, complex)])
全体 文字列が数値として表現できるかどうかを知りたい場合は、正規表現を使用します(または、floatを文字列に変換して元の文字列と比較します)。それほど速くはありません。
私はあなたの解決策は問題ないと思います。
そうは言っても、私が不当だと思うこれらの答えには多くの正規表現が嫌いです。それは本当にあなたがやろうとしていることによります。元の質問は、どのようにして(文字列が数値(float)として表現できるかどうかを確認する)ことができるかどうかでした(あなたのタイトルのとおり)。おそらく、それが有効であることを確認した後で数値/浮動小数点値を使用したいと思うでしょう。その場合、try/exceptは非常に意味があります。しかし、何らかの理由で string が number であることを検証したいだけであれば、正規表現も問題なく動作しますが、正しく取得するのは困難です。私はこれまでのところ大部分の正規表現の答えは、Pythonに関する限り浮動小数点数である整数部分( ".7"のような)がないと文字列を正しく解析しないと思います。そして、小数部分が必要とされない単一の正規表現でチェックするのは少し難しいです。これを示すために2つの正規表現を含めました。
それは「数」が何であるかに関して興味深い質問を提起します。あなたはpythonでfloatとして有効な "inf"を含めますか?それとも「数字」であるがpythonで表現できない数字(例えばfloatの最大値よりも大きい数字など)を含めるか。
数値の解析方法にはあいまいさもあります。たとえば、 " - 20"はどうでしょうか。これは「数」ですか?これは「20」を表すための合法的な方法ですか? Pythonでは、 "var = - 20"を実行して20に設定することはできますが(実際にはこれが式として扱われるためです)、float( " - 20")は機能しません。
とにかく、これ以上の情報がなければ、ここに私はすべての整数と浮動小数点数をカバーすると信じている正規表現です - pythonがそれらを解析するので 。
# Doesn't properly handle floats missing the integer part, such as ".7"
SIMPLE_FLOAT_REGEXP = re.compile(r'^[-+]?[0-9]+\.?[0-9]+([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56" # sign (-)
# integer (12)
# mantissa (34)
# exponent (E+56)
# Should handle all floats
FLOAT_REGEXP = re.compile(r'^[-+]?([0-9]+|[0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56" # sign (-)
# integer (12)
# OR
# int/mantissa (12.34)
# exponent (E+56)
def is_float(str):
return True if FLOAT_REGEXP.match(str) else False
テスト値の例
True <- +42
True <- +42.42
False <- +42.42.22
True <- +42.42e22
True <- +42.42E-22
False <- +42.42e-22.8
True <- .42
False <- 42nope
このコードは、正規表現を使わずに、指数、浮動小数点数、整数を処理します。
return True if str1.lstrip('-').replace('.','',1).isdigit() or float(str1) else False
これが私の簡単なやり方です。私はいくつかの文字列をループ処理していて、それらが数字であることが判明したらそれらを配列に追加したいとしましょう。
try:
myvar.append( float(string_to_check) )
except:
continue
Myvar.apppendを、文字列が数値であることが判明した場合は、その文字列に対して実行する操作に置き換えます。これは、float()操作を使用し、返されたエラーを使用して文字列が数値かどうかを判断することを目的としています。
私はこのスレッドに至るまでの問題、すなわちデータのコレクションを最も直感的な方法で文字列と数値に変換する方法に取り組んでいました。私はオリジナルのコードを読んだ後、私が必要としているのは2つの点で異なることに気付きました。
1 - 文字列が整数を表す場合、整数の結果が欲しい
2 - 数値または文字列の結果をデータ構造に固定したい
だから私はこの派生物を生成するためにオリジナルのコードを修正しました:
def string_or_number(s):
try:
z = int(s)
return z
except ValueError:
try:
z = float(s)
return z
except ValueError:
return s
import re
def is_number(num):
pattern = re.compile(r'^[-+]?[-0-9]\d*\.\d*|[-+]?\.?[0-9]\d*$')
result = pattern.match(num)
if result:
return True
else:
return False
>>>: is_number('1')
True
>>>: is_number('111')
True
>>>: is_number('11.1')
True
>>>: is_number('-11.1')
True
>>>: is_number('inf')
False
>>>: is_number('-inf')
False