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

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

当前回答

Greg Hewgill的方法缺少了几个组件:前导的“^”只匹配字符串的开头,并且预先编译re。但是这种方法可以让你避免尝试:

import re
INT_RE = re.compile(r"^[-]?\d+$")
def RepresentsInt(s):
    return INT_RE.match(str(s)) is not None

我很感兴趣为什么你试图避免尝试:除了?

其他回答

我猜这个问题与速度有关,因为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解决方案似乎更快。

我用的最简单的方法

def is_int(item: str) -> bool:
    return item.lstrip('-+').isdigit()

Greg Hewgill的方法缺少了几个组件:前导的“^”只匹配字符串的开头,并且预先编译re。但是这种方法可以让你避免尝试:

import re
INT_RE = re.compile(r"^[-]?\d+$")
def RepresentsInt(s):
    return INT_RE.match(str(s)) is not None

我很感兴趣为什么你试图避免尝试:除了?

如果你想只接受低ascii码的数字,这里有这样做的测试:

Python 3.7+:(u.isdecimal() and u.isascii()))

Python <= 3.6:(u.isdecimal() and u == str(int(u)))

其他答案建议使用.isdigit()或.isdecimal(),但它们都包含一些上unicode字符,如'缌' (u'\u0662'):

u = u'\u0662'     # '٢'
u.isdigit()       # True
u.isdecimal()     # True
u.isascii()       # False (Python 3.7+ only)
u == str(int(u))  # False

使用正则表达式:

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()只编译正则表达式一次。