如何在不使用try / except的情况下检查字符串是否表示int?


466

有没有办法在不使用try / except机制的情况下判断字符串是否表示一个整数(例如'3''-17'但不是'3.14''asfasfas')?

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

23
为什么两个人都试图这样做?try / except有什么问题?
S.Lott

5
是的,try / except有什么问题?寻求宽恕比获得许可更好。
mk12

53
我想问为什么这个简单的事情需要try / except?异常系统是一个复杂的野兽,但这是一个简单的问题。
艾瓦尔(Aivar)

13
@Aivar停止传播FUD。单个try / except块甚至不接近“复杂”状态。
Triptych

47
不过,这并不是真正的FUD。您将有效地编写4行代码,期望会发生一些问题,捕获该异常并执行默认操作,而不是使用一行代码。
andersonvom

Answers:


398

如果您真的很讨厌在try/except各处使用s,请编写一个辅助函数:

def RepresentsInt(s):
    try: 
        int(s)
        return True
    except ValueError:
        return False

>>> print RepresentsInt("+123")
True
>>> print RepresentsInt("10.0")
False

要完全覆盖Python认为整数的所有字符串,将需要更多的代码。我说这是pythonic。


124
那么用复杂的机制解决简单的问题是pythonic吗?有一种算法可以检测int编写的内部函数“ int”-我不明白为什么不将其显示为布尔函数。
艾瓦尔(Aivar)

79
@Aivar:这5行功能不是复杂的机制。
Triptych

34
除外:>>> print RepresentsInt(10.0) True >>> print RepresentsInt(10.06) True
Dannid 2013年

5
我认为这是“ pythonic”的意思,如果Python认为字符串是int,那么您的程序也是如此。如果Python更改了,您的程序也将更改,并且无需更改任何一行代码。有一些价值。视情况而定,这可能是正确的选择。
沙威2014年

57
我不知道为什么这是被接受的答案或有这么多的投票,因为这与OP要求的完全相反。
FearlessFuture

754

使用正整数可以使用.isdigit

>>> '16'.isdigit()
True

它不适用于负整数。假设您可以尝试以下操作:

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

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

编辑

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

6
如果没有其他特殊情况,则不能处理“ +17”。
布赖恩·奥克利

1
您必须测试以下两种情况:lambda s:s.isdigit()或(s.startswith('-')和s [1:]。isdigit())
抢劫

4
@Roberto:当然应该!并且我确定您有能力这样做!
SilentGhost 2009年

22
注意:u'²'.isdigit()为true,但int(u'²')引发ValueError。使用u.isdecimal()代替。str.isdigit()是依赖于Python 2的语言环境
。– jfs

4
check_int('')将引发异常而不是返回False
wordbug '19

96

您知道,无论出于何种原因,我都发现(并且已经对此进行了反复测试)try / except的效果并不理想。我经常尝试几种做事方法,但我认为我从来没有找到一种使用try / except来最好地完成那些测试的方法,实际上,在我看来,这些方法通常已经接近于最糟糕的,即使不是最糟糕的。并非在每种情况下,但在许多情况下。我知道很多人说这是“ Pythonic”方式,但这是我与他们分开的一个领域。对我来说,它既不是很好的表现也不是非常优雅,因此,我倾向于只将其用于错误捕获和报告。

我要抱怨的是,PHP,perl,ruby,C,甚至是怪异的shell都具有简单的功能来测试整数整数字符串,但是尽力验证这些假设使我大跌眼镜!显然,这种缺乏是一种常见的疾病。

这是布鲁诺帖子的快速而肮脏的编辑:

import sys, time, re

g_intRegex = re.compile(r"^([+-]?[1-9]\d*|0)$")

testvals = [
    # integers
    0, 1, -1, 1.0, -1.0,
    '0', '0.','0.0', '1', '-1', '+1', '1.0', '-1.0', '+1.0', '06',
    # non-integers
    'abc 123',
    1.1, -1.1, '1.1', '-1.1', '+1.1',
    '1.1.1', '1.1.0', '1.0.1', '1.0.0',
    '1.0.', '1..0', '1..',
    '0.0.', '0..0', '0..',
    'one', object(), (1,2,3), [1,2,3], {'one':'two'},
    # with spaces
    ' 0 ', ' 0.', ' .0','.01 '
]

def isInt_try(v):
    try:     i = int(v)
    except:  return False
    return True

def isInt_str(v):
    v = str(v).strip()
    return v=='0' or (v if v.find('..') > -1 else v.lstrip('-+').rstrip('0').rstrip('.')).isdigit()

def isInt_re(v):
    import re
    if not hasattr(isInt_re, 'intRegex'):
        isInt_re.intRegex = re.compile(r"^([+-]?[1-9]\d*|0)$")
    return isInt_re.intRegex.match(str(v).strip()) is not None

def isInt_re2(v):
    return g_intRegex.match(str(v).strip()) is not None

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


def timeFunc(func, times):
    t1 = time.time()
    for n in range(times):
        for v in testvals: 
            r = func(v)
    t2 = time.time()
    return t2 - t1

def testFuncs(funcs):
    for func in funcs:
        sys.stdout.write( "\t%s\t|" % func.__name__)
    print()
    for v in testvals:
        if type(v) == type(''):
            sys.stdout.write("'%s'" % v)
        else:
            sys.stdout.write("%s" % str(v))
        for func in funcs:
            sys.stdout.write( "\t\t%s\t|" % func(v))
        sys.stdout.write("\r\n") 

if __name__ == '__main__':
    print()
    print("tests..")
    testFuncs((isInt_try, isInt_str, isInt_re, isInt_re2, check_int))
    print()

    print("timings..")
    print("isInt_try:   %6.4f" % timeFunc(isInt_try, 10000))
    print("isInt_str:   %6.4f" % timeFunc(isInt_str, 10000)) 
    print("isInt_re:    %6.4f" % timeFunc(isInt_re, 10000))
    print("isInt_re2:   %6.4f" % timeFunc(isInt_re2, 10000))
    print("check_int:   %6.4f" % timeFunc(check_int, 10000))

性能比较结果如下:

timings..
isInt_try:   0.6426
isInt_str:   0.7382
isInt_re:    1.1156
isInt_re2:   0.5344
check_int:   0.3452

AC方法可以扫描一次并完成。我认为,一次扫描字符串的AC方法将是正确的做法。

编辑:

我已经更新了上面的代码以在Python 3.5中工作,并包括了当前投票最多的答案中的check_int函数,并使用了我可以找到的当前最流行的正则表达式来测试整数罩。此正则表达式拒绝诸如“ abc 123”之类的字符串。我添加了“ abc 123”作为测试值。

在这一点上,我非常感兴趣的是要注意,没有一个测试的函数(包括try方法,流行的check_int函数和最流行的用于测试整数罩的正则表达式)会返回所有正确的答案。测试值(嗯,取决于您认为正确答案是什么;请参阅下面的测试结果)。

内置的int()函数会默默地截断浮点数的小数部分,并返回小数点前的整数部分,除非首先将浮点数转换为字符串。

check_int()函数对于0.0和1.0(在技术上是整数)之类的值返回false,对于“ 06”之类的值返回true。

以下是当前(Python 3.5)的测试结果:

                  isInt_try |       isInt_str       |       isInt_re        |       isInt_re2       |   check_int   |
    0               True    |               True    |               True    |               True    |       True    |
    1               True    |               True    |               True    |               True    |       True    |
    -1              True    |               True    |               True    |               True    |       True    |
    1.0             True    |               True    |               False   |               False   |       False   |
    -1.0            True    |               True    |               False   |               False   |       False   |
    '0'             True    |               True    |               True    |               True    |       True    |
    '0.'            False   |               True    |               False   |               False   |       False   |
    '0.0'           False   |               True    |               False   |               False   |       False   |
    '1'             True    |               True    |               True    |               True    |       True    |
    '-1'            True    |               True    |               True    |               True    |       True    |
    '+1'            True    |               True    |               True    |               True    |       True    |
    '1.0'           False   |               True    |               False   |               False   |       False   |
    '-1.0'          False   |               True    |               False   |               False   |       False   |
    '+1.0'          False   |               True    |               False   |               False   |       False   |
    '06'            True    |               True    |               False   |               False   |       True    |
    'abc 123'       False   |               False   |               False   |               False   |       False   |
    1.1             True    |               False   |               False   |               False   |       False   |
    -1.1            True    |               False   |               False   |               False   |       False   |
    '1.1'           False   |               False   |               False   |               False   |       False   |
    '-1.1'          False   |               False   |               False   |               False   |       False   |
    '+1.1'          False   |               False   |               False   |               False   |       False   |
    '1.1.1'         False   |               False   |               False   |               False   |       False   |
    '1.1.0'         False   |               False   |               False   |               False   |       False   |
    '1.0.1'         False   |               False   |               False   |               False   |       False   |
    '1.0.0'         False   |               False   |               False   |               False   |       False   |
    '1.0.'          False   |               False   |               False   |               False   |       False   |
    '1..0'          False   |               False   |               False   |               False   |       False   |
    '1..'           False   |               False   |               False   |               False   |       False   |
    '0.0.'          False   |               False   |               False   |               False   |       False   |
    '0..0'          False   |               False   |               False   |               False   |       False   |
    '0..'           False   |               False   |               False   |               False   |       False   |
    'one'           False   |               False   |               False   |               False   |       False   |
    <obj..>         False   |               False   |               False   |               False   |       False   |
    (1, 2, 3)       False   |               False   |               False   |               False   |       False   |
    [1, 2, 3]       False   |               False   |               False   |               False   |       False   |
    {'one': 'two'}  False   |               False   |               False   |               False   |       False   |
    ' 0 '           True    |               True    |               True    |               True    |       False   |
    ' 0.'           False   |               True    |               False   |               False   |       False   |
    ' .0'           False   |               False   |               False   |               False   |       False   |
    '.01 '          False   |               False   |               False   |               False   |       False   |

刚才我尝试添加此功能:

def isInt_float(s):
    try:
        return float(str(s)).is_integer()
    except:
        return False

它的性能几乎与check_int(0.3486)一样好,并且对于1.0和0.0以及+1.0和0和.0等值返回true。但是它对于'06'也返回true,因此。我猜,选择你的毒药。


也许部分原因是整数本身有点武断。编程系统不能奢望总是以小数表示形式。0x4df在某些地方是有效整数,而在其他地方则不是0891。我害怕考虑在这些检查中给定的unicode会发生什么。
PlexQ 2012年

3
+1的时间。我同意,对于这样一个简单的问题,整个异常业务并不是很优雅。您可能希望针对此类常见问题建立辅助方法...
RickyA 2012年

9
我知道该线程基本上处于休眠状态,但考虑到运行时,则为+1。行长并不总是表明底层的复杂性。当然,try / except看起来很简单(并且易于阅读,这也很重要),但这一项昂贵的操作。我认为首选项层次结构应始终类似于以下内容:1.易于阅读的显式解决方案(SilentGhost的)。2.易于阅读的隐式解决方案(三联式)。3.没有三个。
埃里克·汉弗莱

1
感谢您对这个看似微不足道的话题进行的深入调查。我将使用isInt_str(),是否为pythonic。令我感到困扰的是,我对v.find('..')的含义一无所知。这是某种特殊的查找语法还是数字字符串的边缘情况?
JackLeEmmerdeur

3
是的,有些过时了,但仍然是很好且相关的分析。在Python 3.5 try中效率更高:isInt_try:0.6552 / isInt_str:0.6396 / isInt_re:1.0296 / isInt_re2:0.5168。
戴夫

39

str.isdigit() 应该可以。

例子:

str.isdigit("23") ## True
str.isdigit("abc") ## False
str.isdigit("23.4") ## False

编辑:正如@BuzzMoschetti所指出的那样,这种方式将在减号(例如“ -23”)上失败。如果您的input_num可以小于0,请在应用str.isdigit()之前使用re.sub(regex_search,regex_replace,contents 。例如:

import re
input_num = "-23"
input_num = re.sub("^-", "", input_num) ## "^" indicates to remove the first "-" only
str.isdigit(input_num) ## True

1
因为-23产生false。
Buzz Moschetti

1
@BuzzMoschetti,您是对的。一种快速解决的方法是在应用str.isdigit()之前通过re.replace(regex_search,regex_replace,contents)删除减号
Catbuilts

27

使用正则表达式:

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()


19
+1:表明与try / except相比,这非常复杂且昂贵。
S.Lott

2
我觉得这实际上是@SilentGhost提供的'isnumeric'解决方案的较慢的自定义版本。
格雷格,

@Greg:由于@SilentGhost不能正确覆盖符号,因此此版本实际上有效。
S.Lott

1
@ S.Lott:毫无疑问,任何能够在SO上发布信息的人都可以将我的示例扩展到涵盖标志。
SilentGhost

2
正则表达式是关于存在的最复杂和晦涩的事物,我发现上面的简单检查实际上更加清晰,即使我认为它仍然很丑,这也很丑。
PlexQ 2012年

18

适当的RegEx解决方案将结合Greg Hewgill和Nowell的想法,但不使用全局变量。您可以通过将属性附加到方法来完成此操作。另外,我知道将导入放在一种方法中并不容易,但是我要使用的是“惰性模块”效果,例如http://peak.telecommunity.com/DevCenter/Importing#lazy-imports

编辑:到目前为止,我最喜欢的技术是仅使用String对象的方法。

#!/usr/bin/env python

# Uses exclusively methods of the String object
def isInteger(i):
    i = str(i)
    return i=='0' or (i if i.find('..') > -1 else i.lstrip('-+').rstrip('0').rstrip('.')).isdigit()

# Uses re module for regex
def isIntegre(i):
    import re
    if not hasattr(isIntegre, '_re'):
        print("I compile only once. Remove this line when you are confident in that.")
        isIntegre._re = re.compile(r"[-+]?\d+(\.0*)?$")
    return isIntegre._re.match(str(i)) is not None

# When executed directly run Unit Tests
if __name__ == '__main__':
    for obj in [
                # integers
                0, 1, -1, 1.0, -1.0,
                '0', '0.','0.0', '1', '-1', '+1', '1.0', '-1.0', '+1.0',
                # non-integers
                1.1, -1.1, '1.1', '-1.1', '+1.1',
                '1.1.1', '1.1.0', '1.0.1', '1.0.0',
                '1.0.', '1..0', '1..',
                '0.0.', '0..0', '0..',
                'one', object(), (1,2,3), [1,2,3], {'one':'two'}
            ]:
        # Notice the integre uses 're' (intended to be humorous)
        integer = ('an integer' if isInteger(obj) else 'NOT an integer')
        integre = ('an integre' if isIntegre(obj) else 'NOT an integre')
        # Make strings look like strings in the output
        if isinstance(obj, str):
            obj = ("'%s'" % (obj,))
        print("%30s is %14s is %14s" % (obj, integer, integre))

对于班级较少的成员,输出如下:

I compile only once. Remove this line when you are confident in that.
                             0 is     an integer is     an integre
                             1 is     an integer is     an integre
                            -1 is     an integer is     an integre
                           1.0 is     an integer is     an integre
                          -1.0 is     an integer is     an integre
                           '0' is     an integer is     an integre
                          '0.' is     an integer is     an integre
                         '0.0' is     an integer is     an integre
                           '1' is     an integer is     an integre
                          '-1' is     an integer is     an integre
                          '+1' is     an integer is     an integre
                         '1.0' is     an integer is     an integre
                        '-1.0' is     an integer is     an integre
                        '+1.0' is     an integer is     an integre
                           1.1 is NOT an integer is NOT an integre
                          -1.1 is NOT an integer is NOT an integre
                         '1.1' is NOT an integer is NOT an integre
                        '-1.1' is NOT an integer is NOT an integre
                        '+1.1' is NOT an integer is NOT an integre
                       '1.1.1' is NOT an integer is NOT an integre
                       '1.1.0' is NOT an integer is NOT an integre
                       '1.0.1' is NOT an integer is NOT an integre
                       '1.0.0' is NOT an integer is NOT an integre
                        '1.0.' is NOT an integer is NOT an integre
                        '1..0' is NOT an integer is NOT an integre
                         '1..' is NOT an integer is NOT an integre
                        '0.0.' is NOT an integer is NOT an integre
                        '0..0' is NOT an integer is NOT an integre
                         '0..' is NOT an integer is NOT an integre
                         'one' is NOT an integer is NOT an integre
<object object at 0x103b7d0a0> is NOT an integer is NOT an integre
                     (1, 2, 3) is NOT an integer is NOT an integre
                     [1, 2, 3] is NOT an integer is NOT an integre
                {'one': 'two'} is NOT an integer is NOT an integre

4
我同意我的测试套件过大。我想证明我的代码在编写时是有效的。但是,您认为我的isInteger函数过大吗?当然不是。
布鲁诺·布罗诺斯基

1
我只是没有任何评论的否决票。人是什么?我知道千禧一代现在使用“喜欢”作为“已读回执”。但是他们现在是否使用否决票作为“不是我选择的方法”标记?也许他们没有意识到这会从您自己的声誉中减去2分来否决答案。SO / SE这样做是为了鼓励仅由于错误信息而拒绝投票,在这种情况下,我希望您能发表评论
布鲁诺·布鲁诺斯基

5
>>> "+7".lstrip("-+").isdigit()
True
>>> "-7".lstrip("-+").isdigit()
True
>>> "7".lstrip("-+").isdigit()
True
>>> "13.4".lstrip("-+").isdigit()
False

因此,您的功能将是:

def is_int(val):
   return val[1].isdigit() and val.lstrip("-+").isdigit()

1
is_int(“ 2”)引发IndexError。
anttikoo

4

Greg Hewgill的方法缺少一些组件:前导“ ^”只匹配字符串的开头,然后预先编译re。但是这种方法将使您避免尝试:专家:

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

我很想知道为什么您要尝试避免尝试:除了?


1
一个风格的问题。我认为“ try / except”仅应用于实际错误,而不能用于正常程序流程。
亚当·马坦

2
@Udi Pasmon:除了“正常”程序流程外,Python大量使用try /。例如,每个迭代器都会在引发异常的情况下停止。
S.Lott

3
-1:虽然你在暗示编译正则表达式是正确的,你错了,在其他方面critizising格雷格:re.match比赛对抗开始的字符串,所以^在模式实际上是多余的。(使用re.search时这是不同的)。
ThomasH

S.Lott-这在python中被认为是合理的流程吗?这与其他语言有何不同?也许值得单独提出一个问题。
亚当·马坦

1
SO涵盖了Python对try / except的大量使用。尝试搜索“ [python] except”
S.Lott

4

我必须一直这样做,而且我对使用try / except模式有轻微但不合理的厌恶感。我用这个:

all([xi in '1234567890' for xi in x])

它不包含负数,因此您可以去除一个减号(如果有),然后检查结果是否包含0-9的数字:

all([xi in '1234567890' for xi in x.replace('-', '', 1)])

如果不确定输入是否为字符串,也可以将x传递给str():

all([xi in '1234567890' for xi in str(x).replace('-', '', 1)])

至少有两种(边缘?)情况会崩溃:

  1. 它不适用于各种科学和/或指数表示法(例如1.2E3、10 ^ 3等)-两者都将返回False。我也不认为其他答案也可以解决这个问题,甚至Python 3.8也有不一致的意见,因为type(1E2)给出了<class 'float'>type(10^2)给出了<class 'int'>
  2. 空字符串输入为True。

因此,它不适用于所有可能的输入,但是如果您可以排除科学计数法,指数计数法和空字符串,则可以单行检查,False如果x不是整数,True并且x是整数,则返回单行检查。

我不知道它是否是pythonic,但这只是一行,而且相对清楚代码的作用。


尝试/例外似乎就像在某人的草坪上行走(尝试),然后如果/当他们注意到并生气时(例外),您表示道歉(处理例外),而我的all(xi in '1234567890' for xi in x])模式似乎更像是请求允许在草坪上行走。我很高兴成为许可请求者,但是我们来了。
mRotten

3

我认为

s.startswith('-') and s[1:].isdigit()

最好重写为:

s.replace('-', '').isdigit()

因为s [1:]也创建了一个新字符串

但是更好的解决方案是

s.lstrip('+-').isdigit()

3
猜猜是什么replace?另外,5-2例如,这将错误地接受。
Ry-

如果发生以下情况,则会引发IndexError错误:s='-'
Anti Earth

s ='-'; s.replace('-','').isdigit()-> False
Vladyslav Savchenko

2

我真的很喜欢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 ()函数,因此即使执行时间略有不同,我也将其包含在内。(而且这两种方法都击败了其他一切,但是不处理多余的东西:“ ./+/-”)

此外,我确实发现有趣的是注意到正则表达式(isInt_re2方法)在Shavais于2012年(当前为2018年)执行的同一测试中击败了字符串比较。也许正则表达式库得到了改进?


1

在我看来,这可能是最直接,最Python的方法。我没有看到这种解决方案,它与regex基本相同,但是没有regex。

def is_int(test):
    import string
    return not (set(test) - set(string.digits))

set(input_string) == set(string.digits)如果我们跳过'-+ '在开始时和.0E-1底。
jfs

1

这是一个不会引起错误的解析函数。它处理明显的None失败案例(在CPython上默认处理多达2000个“-/ +”符号!):

#!/usr/bin/env python

def get_int(number):
    splits = number.split('.')
    if len(splits) > 2:
        # too many splits
        return None
    if len(splits) == 2 and splits[1]:
        # handle decimal part recursively :-)
        if get_int(splits[1]) != 0:
            return None

    int_part = splits[0].lstrip("+")
    if int_part.startswith('-'):
        # handle minus sign recursively :-)
        return get_int(int_part[1:]) * -1
    # successful 'and' returns last truth-y value (cast is always valid)
    return int_part.isdigit() and int(int_part)

一些测试:

tests = ["0", "0.0", "0.1", "1", "1.1", "1.0", "-1", "-1.1", "-1.0", "-0", "--0", "---3", '.3', '--3.', "+13", "+-1.00", "--+123", "-0.000"]

for t in tests:
    print "get_int(%s) = %s" % (t, get_int(str(t)))

结果:

get_int(0) = 0
get_int(0.0) = 0
get_int(0.1) = None
get_int(1) = 1
get_int(1.1) = None
get_int(1.0) = 1
get_int(-1) = -1
get_int(-1.1) = None
get_int(-1.0) = -1
get_int(-0) = 0
get_int(--0) = 0
get_int(---3) = -3
get_int(.3) = None
get_int(--3.) = 3
get_int(+13) = 13
get_int(+-1.00) = -1
get_int(--+123) = 123
get_int(-0.000) = 0

根据您的需要,您可以使用:

def int_predicate(number):
     return get_int(number) is not None

1

我建议以下内容:

import ast

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

文档

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

我应该注意,ValueError当对任何不构成Python文字的内容进行调用时,这将引发异常。由于问题要求的解决方案没有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

¯\ _(ツ)_ /¯


0

我有一种根本不使用int的可能性,并且除非字符串不代表数字,否则不应引发异常

float(number)==float(number)//1

它应该适用于float接受的任何类型的字符串(正,负,工程符号)。


0

我猜这个问题与速度有关,因为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字符串,np.core.defchararray.isnumeric(u'+12')但是它返回和数组。因此,如果您必须进行数千次转换并且缺少数据或非数字数据,这是一个很好的解决方案。

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解决方案要快得多。


0

如果您只想接受低位数字,请执行以下测试:

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

这将不会处理负值或空格填充值,这两个值都可以通过很好地处理int()
ShadowRanger

-6

嗯。尝试这个:

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

如果您不输入不是数字的字符串,则此方法有效。

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

a = 2
a.isdigit()

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


我认为您需要在2赋予的值周围加引号a
路加·伍德沃德

1
为什么这不是最高答案?它准确地回答了这个问题。

6
-1问题:“检查字符串是否表示int,而不使用Try / Except?” for @Caroline Alexiou
jfs
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.