Вопрос-Ответ

How do I check if a string represents a number (float or int)?

Как мне проверить, представляет ли строка число (float или int)?

Как мне проверить, представляет ли строка числовое значение в Python?

def is_number(s):
try:
float(s)
return True
except ValueError:
return False

Вышеописанное работает, но кажется неуклюжим.


Если то, что вы тестируете, исходит из пользовательского ввода, это все равно строка , даже если она представляет an int или a float. Смотрите Как я могу считывать входные данные как числа? для преобразования входных данных и запроса у пользователя входных данных до тех пор, пока он не выдаст корректный ответ для обеспечения того, чтобы входные данные представляли int or float (или другие требования), прежде чем продолжить.

Переведено автоматически
Ответ 1

Только для неотрицательных (беззнаковых) целых чисел используйте isdigit():

>>> a = "03523"
>>> a.isdigit()
True
>>> b = "963spam"
>>> b.isdigit()
False

Документация для isdigit(): Python2, Python3

Для строк Python 2 в Юникоде: isnumeric().

Ответ 2

Что не только уродливо и медленно


Я бы оспорил оба варианта.

Регулярное выражение или другой метод синтаксического анализа строк был бы более уродливым и медленным.

Я не уверен, что что-то намного быстрее, чем указано выше. Это вызывает функцию и возвращает результат. Try / Catch не приводит к большим накладным расходам, потому что наиболее распространенное исключение перехватывается без тщательного поиска фреймов стека.

Проблема в том, что любая функция преобразования чисел имеет два вида результатов


  • Число, если оно допустимо

  • Код состояния (например, через errno) или исключение, чтобы показать, что не удалось разобрать ни одно допустимое число.

C (в качестве примера) использует несколько способов обойти это. Python излагает это четко и недвусмысленно.

Я думаю, что ваш код для этого идеален.

Ответ 3

TL; DR Лучшим решением является s.replace('.','',1).isdigit()

Я провел несколько тестов, сравнивая различные подходы

def is_number_tryexcept(s):
""" Returns True if string is a number. """
try:
float(s)
return True
except ValueError:
return False

import re
def is_number_regex(s):
""" Returns True if 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 if string is a number. """
return s.replace('.','',1).isdigit()

Если строка не является числом, блок except выполняется довольно медленно. Но что более важно, метод 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('Научная нотация "1.000000e+50" не поддерживается:') для f в функциях: если не f(scientific1): print('\t -', f.имя)


    print('Научная нотация "1e50" не поддерживается:') для f в функциях: если не 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 if string is a number. """
try:
float(s)
return True
except ValueError:
return False

def is_number_regex(s):
""" Returns True if 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 if string is a number. """
if comp.match(s) is None:
return s.isdigit()
return True


def is_number_repl_isdigit(s):
""" Returns True if string is a number. """
return s.replace('.','',1).isdigit()

введите описание изображения здесь

Ответ 4

Есть одно исключение, которое вы, возможно, захотите принять во внимание: строка 'NaN'

Если вы хотите, чтобы is_number возвращал FALSE для 'NaN', этот код не будет работать, поскольку Python преобразует его в свое представление числа, которое не является числом (поговорим о проблемах с идентификацией):

>>> float('NaN')
nan

В противном случае, я должен поблагодарить вас за фрагмент кода, который я сейчас широко использую. :)

G.

python