有没有办法告诉一个字符串是否代表一个整数(例如,'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有一个时间惩罚:
测试数据
首先,我创建了一个包含200个字符串、100个失败字符串和100个数字字符串的列表。
from random import shuffle
numbers = [u'+1'] * 100
nonumbers = [u'1abc'] * 100
testlist = numbers + nonumbers
shuffle(testlist)
testlist = np.array(testlist)
numpy解决方案(仅适用于数组和unicode)
Np.core.defchararray.isnumeric也可以用于unicode字符串,但它返回一个数组。所以,如果你必须做成千上万的转换,并且有丢失的数据或非数值数据,这是一个很好的解决方案。
import numpy as np
%timeit np.core.defchararray.isnumeric(testlist)
10000 loops, best of 3: 27.9 µs per loop # 200 numbers per loop
试/除了
def check_num(s):
try:
int(s)
return True
except:
return False
def check_list(l):
return [check_num(e) for e in l]
%timeit check_list(testlist)
1000 loops, best of 3: 217 µs per loop # 200 numbers per loop
numpy解决方案似乎更快。
其他回答
Greg Hewgill的方法缺少了几个组件:前导的“^”只匹配字符串的开头,并且预先编译re。但是这种方法可以让你避免尝试:
import re
INT_RE = re.compile(r"^[-]?\d+$")
def RepresentsInt(s):
return INT_RE.match(str(s)) is not None
我很感兴趣为什么你试图避免尝试:除了?
使用正则表达式:
import re
def RepresentsInt(s):
return re.match(r"[-+]?\d+$", s) is not None
如果你必须接受小数也:
def RepresentsInt(s):
return re.match(r"[-+]?\d+(\.0*)?$", s) is not None
如果经常这样做,为了提高性能,请使用re.compile()只编译正则表达式一次。
我一直这样做,我对使用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。所以前面有偶数个负号就会得到一个正整数,前面有奇数个负号就会得到一个负整数,但结果总是整数。
检查后将值转换为字符串为整数,然后检查字符串第一个字符值为-或+,其余字符串为数字。最后检查isdigit。 Test = ['1', '12015', '1..]2 ', ' a2kk78”、“1.5”,2,1.24,“-8.5”,“+”、“1”、“88751.71 + 7)
检查
for k,v in enumerate(test):
print(k, v, 'test: ', True if isinstance(v, int) is not False else True if str(v)[0] in ['-', '+'] and str(v)[1:].isdigit() else str(v).isdigit())
结果
0 1 test: True
1 12015 test: True
2 1..2 test: False
3 a2kk78 test: False
4 1.5 test: False
5 2 test: True
6 1.24 test: False
7 -8.5 test: False
8 +88751.71 test: False
9 -1 test: True
10 +7 test: True
我真的很喜欢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执行的相同测试中击败了字符串比较。也许正则表达式库已经改进了?