Ответ зависит от того, что вы подразумеваете под «числовой строкой». Если ваше определение числовой строки - «все, что допускает float», то трудно улучшить метод try-except.
Но имейте в виду, что плавание может быть более либеральным, чем вы хотите: на большинстве машин он примет строки, представляющие бесконечности и nans. Например, на моей машине он принимает 'nan(dead!$#parrot)'
. Он также будет принимать начальные и конечные пробелы. И в зависимости от вашего приложения вы можете исключить экспоненциальные представления float. В этих случаях использование регулярного выражения имеет смысл. Чтобы просто исключить бесконечности и nans, было бы проще использовать метод try-except, а затем использовать math.isnan и math.isinf для проверки результата преобразования.
Написание правильного регулярного выражения для числовых строк является удивительно сложной задачей. Например, ваша функция IsNumber2
принимает строку '.'
. Вы можете найти проверенную временем версию регулярного выражения с числовой строкой в источнике десятичного модуля. Здесь (с некоторыми незначительными правками):
_parser = re.compile(r""" # A numeric string consists of:
(?P<sign>[-+])? # an optional sign, followed by either...
(
(?=\d|\.\d) # ...a number (with at least one digit)
(?P<int>\d*) # having a (possibly empty) integer part
(\.(?P<frac>\d*))? # followed by an optional fractional part
(E(?P<exp>[-+]?\d+))? # followed by an optional exponent, or...
|
Inf(inity)? # ...an infinity, or...
|
(?P<signal>s)? # ...an (optionally signaling)
NaN # NaN
(?P<diag>\d*) # with (possibly empty) diagnostic info.
)
\Z
""", re.VERBOSE | re.IGNORECASE | re.UNICODE).match
Это в значительной степени матчей именно то, что поплавок принимает, для передних и задних пробелов, за исключением, и некоторые незначительные различия для NaNs (дополнительный «s» для сигнализации пренебрежима малых и диагностическая информация). Когда мне нужно числовое регулярное выражение, я обычно начинаю с этого и редактирую биты, которые мне не нужны.
N.B. Это мыслимое, что float может быть медленнее, чем регулярное выражение, так как он должен не только разбирать строку, но также превращать ее в float, что является довольно сложным вычислением; однако это все равно было бы сюрпризом.
Первый способ является правильным и полезным. Второй косвенный и имеет несколько тонких ошибок. –
@Mike Graham: Ваш комментарий звучит как ответ.Пожалуйста, удалите комментарий, опубликуйте ответ, и мы можем его продвинуть правильно. –
Еще одна ошибка в вашем регулярном выражении: вам нужно избежать этого. перед ? если вы не хотите, чтобы 123z45 считался «числом». –