有没有办法告诉一个字符串是否代表一个整数(例如,'3','-17'但不是'3.14'或'asfasfas')而不使用try/except机制?
is_int('3.14') == False
is_int('-7') == True
有没有办法告诉一个字符串是否代表一个整数(例如,'3','-17'但不是'3.14'或'asfasfas')而不使用try/except机制?
is_int('3.14') == False
is_int('-7') == True
当前回答
我一直这样做,我对使用try/except模式有一种温和但不可否认的非理性厌恶。我用这个:
all([xi in '1234567890' for xi in x])
它不包含负数,所以你可以去掉左边所有的负号,然后检查结果是否包含0-9之间的数字:
all([xi in '1234567890' for xi in x.lstrip('-')])
如果你不确定输入是字符串,你也可以将x传递给str():
all([xi in '1234567890' for xi in str(x).lstrip('-')])
有一些(边缘?)情况下,这是行不通的:
It doesn't work for various scientific and/or exponential notations (e.g. 1.2E3, 10^3, etc.) - both will return False. I don't think other answers accommodated this either, and even Python 3.8 has inconsistent opinions, since type(1E2) gives <class 'float'> whereas type(10^2) gives <class 'int'>. An empty string input gives True. A leading plus sign (e.g. "+7") gives False. Multiple minus signs are ignored so long as they're leading characters. This behavior is similar to the python interpreter* in that type(---1) returns <class int>. However, it isn't completely consistent with the interpreter in that int('---1') gives an error, but my solution returns True with the same input.
所以它不会对所有可能的输入都有效,但如果你能排除这些,这是一个OK的单行检查,如果x不是整数返回False,如果x是整数返回True。但是如果你真的想要精确模拟int()内置的行为,你最好使用try/except。
我不知道这是否是python式的,但它只有一行,而且代码的功能相对清晰。
我并不是说解释器忽略了前导负号,只是说任何数量的前导负号都不会改变结果是整数。Int(——1)实际上被解释为-(-1)或1。Int(——1)被解释为-(-(-1)),或者-1。所以前面有偶数个负号就会得到一个正整数,前面有奇数个负号就会得到一个负整数,但结果总是整数。
其他回答
呃. .试试这个:
def int_check(a):
if int(a) == a:
return True
else:
return False
如果你不输入非数字的字符串,这是可行的。
还有(我忘了写数字检查部分了。),有一个函数检查字符串是否是数字。它是str.isdigit()。这里有一个例子:
a = 2
a.isdigit()
如果调用a.s isdigit(),它将返回True。
如果你真的不喜欢到处使用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()
我的建议如下:
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
¯\_(五)_/¯
先决条件:
我们谈论的是整数(不是小数/浮点数); 内置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