有没有办法告诉一个字符串是否代表一个整数(例如,'3','-17'但不是'3.14'或'asfasfas')而不使用try/except机制?

is_int('3.14') == False
is_int('-7')   == True

当前回答

我的建议如下:

import ast

def is_int(s):
    return isinstance(ast.literal_eval(s), int)

从文档中可以看出:

安全地计算表达式节点或包含Python文字或容器显示的字符串。提供的字符串或节点只能由以下Python文字结构组成:字符串、字节、数字、元组、列表、字典、集、布尔值和None。

我应该指出,当对任何不构成Python文字的内容调用时,这将引发ValueError异常。因为这个问题要求一个没有try/except的解决方案,我有一个Kobayashi-Maru类型的解决方案:

from ast import literal_eval
from contextlib import suppress

def is_int(s):
    with suppress(ValueError):
        return isinstance(literal_eval(s), int)
    return False

¯\_(五)_/¯

其他回答

我真的很喜欢Shavais的帖子,但我又添加了一个测试用例(&内置的isdigit()函数):

def isInt_loop(v):
    v = str(v).strip()
    # swapping '0123456789' for '9876543210' makes nominal difference (might have because '1' is toward the beginning of the string)
    numbers = '0123456789'
    for i in v:
        if i not in numbers:
            return False
    return True

def isInt_Digit(v):
    v = str(v).strip()
    return v.isdigit()

而且它一直明显优于其他时代:

timings..
isInt_try:   0.4628
isInt_str:   0.3556
isInt_re:    0.4889
isInt_re2:   0.2726
isInt_loop:   0.1842
isInt_Digit:   0.1577

使用普通2.7 python:

$ python --version
Python 2.7.10

我添加的两个测试用例(isInt_loop和isInt_digit)都通过了完全相同的测试用例(它们都只接受无符号整数),但我认为人们可以更聪明地修改字符串实现(isInt_loop)而不是内置的isdigit()函数,所以我包括了它,尽管执行时间略有不同。(这两种方法都比其他方法好很多,但没有处理额外的东西:“。/ + / -)

此外,我发现有趣的是,regex (isInt_re2方法)在2012年(目前是2018年)由Shavais执行的相同测试中击败了字符串比较。也许正则表达式库已经改进了?

如果你真的不喜欢到处使用try/except,请写一个helper函数:

def represents_int(s):
    try: 
        int(s)
    except ValueError:
        return False
    else:
        return True
>>> print(represents_int("+123"))
True
>>> print(represents_int("10.0"))
False

它将需要更多的代码来精确覆盖Python认为是整数的所有字符串。要我说,你就用蟒语吧。

对于正整数,可以使用.isdigit:

>>> '16'.isdigit()
True

但它对负整数不起作用。假设您可以尝试以下方法:

>>> s = '-17'
>>> s.startswith('-') and s[1:].isdigit()
True

它不适用于'16.0'格式,在这个意义上,'16.0'格式类似于int类型强制转换。

编辑:

def check_int(s):
    if s[0] in ('-', '+'):
        return s[1:].isdigit()
    return s.isdigit()

先决条件:

我们谈论的是整数(不是小数/浮点数); 内置int()的行为是我们的标准(有时很奇怪:“-00”是它的正确输入)

简短的回答:

使用下面的代码。它简单,正确(虽然这个线程中的许多变体不是),并且几乎是try/except和regex变体的两倍。

def is_int_str(string):
    return (
        string.startswith(('-', '+')) and string[1:].isdigit()
    ) or string.isdigit()

TL;博士答:

我已经测试了3个主要变体(1)try/except, (2) re.match()和(3)字符串操作(见上文)。第三个变体比try/except和re.match()快两倍。顺便说一句:regex变体是最慢的!请参见下面的测试脚本。

import re
import time


def test(func, test_suite):
    for test_case in test_suite:
        actual_result = func(*test_case[0])
        expected_result = test_case[1]
        assert (
            actual_result == expected_result
        ), f'Expected: {expected_result} but actual: {actual_result}'


def perf(func, test_suite):
    start = time.time()

    for _ in range(0, 1_000_000):
        test(func, test_suite)

    return time.time() - start


def is_int_str_1(string):
    try:
        int(string)
        return True
    except ValueError:
        return False


def is_int_str_2(string):
    return re.match(r'^[\-+]?\d+$', string) is not None


def is_int_str_3(string):
    return (
        string.startswith(('-', '+')) and string[1:].isdigit()
    ) or string.isdigit()


# Behavior of built-in int() function is a standard for the following tests
test_suite = [
    [['1'], True],  # func('1') -> True
    [['-1'], True],
    [['+1'], True],
    [['--1'], False],
    [['++1'], False],
    [['001'], True],  # because int() can read it
    [['-00'], True],  # because of quite strange behavior of int()
    [['-'], False],
    [['abracadabra'], False],
    [['57938759283475928347592347598357098458405834957984755200000000'], True],
]

time_span_1 = perf(is_int_str_1, test_suite)
time_span_2 = perf(is_int_str_2, test_suite)
time_span_3 = perf(is_int_str_3, test_suite)

print(f'{is_int_str_1.__name__}: {time_span_1} seconds')
print(f'{is_int_str_2.__name__}: {time_span_2} seconds')
print(f'{is_int_str_3.__name__}: {time_span_3} seconds')

输出是:

is_int_str_1: 4.314162969589233 seconds
is_int_str_2: 5.7216269969940186 seconds
is_int_str_3: 2.5828163623809814 seconds

呃. .试试这个:

def int_check(a):
    if int(a) == a:
        return True
    else:
        return False

如果你不输入非数字的字符串,这是可行的。

还有(我忘了写数字检查部分了。),有一个函数检查字符串是否是数字。它是str.isdigit()。这里有一个例子:

a = 2
a.isdigit()

如果调用a.s isdigit(),它将返回True。