如何检查字符串是否表示一个数字(浮点数或整数)?

1977 投票
41 回答
1741787 浏览
提问于 2025-04-11 20:20

我怎么检查一个字符串在Python中是否表示一个数字?

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

上面的做法可以,但感觉有点笨重。


如果你测试的内容来自用户输入,即使它看起来像一个数字,它仍然是一个字符串。想了解如何把输入转换成数字,可以查看如何将输入读取为数字?,而如果你想确保用户输入的是有效的数字,可以参考让用户输入直到他们给出有效的响应,这样可以确保输入的是一个整数或浮点数(或者其他要求)后再继续。

41 个回答

334

总结 最好的解决方案是 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()

如果字符串不是一个数字,异常处理的部分会比较慢。但更重要的是,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

    科学计数法示例1 = '1.000000e+50'

    科学计数法示例2 = '1e50'

    打印('科学计数法 "1.000000e+50" 不被以下方法支持:')

    对于每个方法:

    如果这个方法不支持科学计数法示例1:

    打印('\t -', 方法.名称)

    打印('科学计数法 "1e50" 不被以下方法支持:')

    对于每个方法:

    如果这个方法不支持科学计数法示例2:

    打印('\t -', 方法.名称)

科学计数法 "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()

在这里输入图片描述

1782

对于非负整数(也就是不带负号的整数),可以使用 isdigit() 这个方法:

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

isdigit() 的文档说明可以在这里找到: Python2Python3

如果你在使用 Python 2 的 Unicode 字符串,可以用 isnumeric() 这个方法。

780

这不仅看起来丑,而且速度慢。

我对此有不同的看法。

用正则表达式或者其他字符串解析方法会更丑也更慢。

我不太确定还有什么比上面的方法更快。它只是调用一个函数然后返回。使用尝试/捕获(Try/Catch)并不会增加太多负担,因为最常见的异常是直接捕获的,不需要在堆栈帧中进行复杂的搜索。

问题在于,任何数字转换函数都有两种结果:

  • 如果数字有效,就返回一个数字。
  • 如果没有有效的数字可以解析,就返回一个状态码(比如通过errno)或者抛出一个异常。

以C语言为例,它有很多方法来处理这个问题。而Python则清晰明确地展示了这一点。

我觉得你写的代码做得很好。

撰写回答