如何在不使用 try/ except 的情况下检查字符串是否代表 int?
有没有办法判断字符串是否代表整数(例如'3'
、'-17'
但不是' 3.14'
或 'asfasfas'
) 不使用 try/except 机制?
is_int('3.14') == False
is_int('-7') == True
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(23)
如果您真的对到处使用
try/ except
感到恼火,请编写一个辅助函数:要完全覆盖 Python 认为是整数的所有字符串,需要更多的代码。 我想说的是,在这个问题上要Pythonic一点。
If you're really just annoyed at using
try/except
s all over the place, please just write a helper function:It's going to be WAY more code to exactly cover all the strings that Python considers integers. I say just be pythonic on this one.
你知道,我发现(并且我已经一遍又一遍地测试了这一点)无论出于何种原因, try/ except 的性能都不是很好。 我经常尝试几种做事的方法,而且我认为我还没有找到一种使用 try/ except 来执行测试中最好的方法,事实上,在我看来,这些方法通常都接近于最糟糕的,即使不是最糟糕的。 不是在所有情况下,但在很多情况下。 我知道很多人说这是“Pythonic”方式,但这是我与他们不同的地方。 对我来说,它既不是很高效,也不是很优雅,因此,我倾向于仅将它用于错误捕获和报告。
我本来想抱怨 PHP、perl、ruby、C,甚至该死的 shell 都有简单的函数来测试字符串的整数范围,但验证这些假设的尽职调查让我绊倒了! 显然,这种缺乏是一种常见病。
以下是对 Bruno 帖子的快速而粗略的编辑:
以下是性能比较结果:
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)的测试结果:
刚才我尝试添加此函数:
它的性能几乎与 check_int (0.3486) 一样好,并且对于 1.0 和 0.0 以及 +1.0 和 0. 和 .0 等值返回 true在。 但对于“06”它也返回 true,所以。 我想,选择你的毒药吧。
You know, I've found (and I've tested this over and over) that try/except does not perform all that well, for whatever reason. I frequently try several ways of doing things, and I don't think I've ever found a method that uses try/except to perform the best of those tested, in fact it seems to me those methods have usually come out close to the worst, if not the worst. Not in every case, but in many cases. I know a lot of people say it's the "Pythonic" way, but that's one area where I part ways with them. To me, it's neither very performant nor very elegant, so, I tend to only use it for error trapping and reporting.
I was going to gripe that PHP, perl, ruby, C, and even the freaking shell have simple functions for testing a string for integer-hood, but due diligence in verifying those assumptions tripped me up! Apparently this lack is a common sickness.
Here's a quick and dirty edit of Bruno's post:
Here are the performance comparison results:
A C method could scan it Once Through, and be done. A C method that scans the string once through would be the Right Thing to do, I think.
EDIT:
I've updated the code above to work in Python 3.5, and to include the check_int function from the currently most voted up answer, and to use the current most popular regex that I can find for testing for integer-hood. This regex rejects strings like 'abc 123'. I've added 'abc 123' as a test value.
It is Very Interesting to me to note, at this point, that NONE of the functions tested, including the try method, the popular check_int function, and the most popular regex for testing for integer-hood, return the correct answers for all of the test values (well, depending on what you think the correct answers are; see the test results below).
The built-in int() function silently truncates the fractional part of a floating point number and returns the integer part before the decimal, unless the floating point number is first converted to a string.
The check_int() function returns false for values like 0.0 and 1.0 (which technically are integers) and returns true for values like '06'.
Here are the current (Python 3.5) test results:
Just now I tried adding this function:
It performs almost as well as check_int (0.3486) and it returns true for values like 1.0 and 0.0 and +1.0 and 0. and .0 and so on. But it also returns true for '06', so. Pick your poison, I guess.
使用正则表达式:
如果您还必须接受小数:
如果您经常这样做,为了提高性能,请仅使用
re.compile()
编译正则表达式一次。Use a regular expression:
If you must accept decimal fractions also:
For improved performance if you're doing this often, compile the regular expression only once using
re.compile()
.str.isdigit()
应该可以解决问题。示例:
编辑:
正如 @BuzzMoschetti 指出的,这种方式对于负数(例如“-23”)会失败。 如果您的 input_num 可能小于 0,请在应用 str.isdigit() 之前使用 re.sub(regex_search,regex_replace,contents)。 例如:
str.isdigit()
should do the trick.Examples:
EDIT:
As @BuzzMoschetti pointed out, this way will fail for minus number (e.g, "-23"). In case your input_num can be less than 0, use re.sub(regex_search,regex_replace,contents) before applying str.isdigit(). For example:
正确的 RegEx 解决方案将结合 Greg Hewgill 和 Nowell 的想法,但不使用全局变量。 您可以通过将属性附加到方法来实现此目的。 另外,我知道将导入放入方法中是不受欢迎的,但我想要的是“惰性模块”效果,例如 http://peak.telecommunity.com/DevCenter/Importing#lazy-imports
编辑: 到目前为止我最喜欢的技术是使用独占方法String 对象的。
对于班级中不太喜欢冒险的成员,以下是输出:
The proper RegEx solution would combine the ideas of Greg Hewgill and Nowell, but not use a global variable. You can accomplish this by attaching an attribute to the method. Also, I know that it is frowned upon to put imports in a method, but what I'm going for is a "lazy module" effect like http://peak.telecommunity.com/DevCenter/Importing#lazy-imports
edit: My favorite technique so far is to use exclusively methods of the String object.
And for the less adventurous members of the class, here is the output:
所以你的函数是:
So your function would be:
我一直这样做,因为我对使用 try/ except 模式有轻微但不可否认的非理性厌恶。 我用这个:
它不容纳负数,所以你可以去掉左侧的所有减号,然后检查结果是否包含 0-9 的数字:
如果你',你也可以将 x 传递给 str()不确定输入是字符串:
有一些(边缘?)情况会崩溃:
type(1E2)
给出
而>type(10^2)
给出
。type(---1)
返回
。 但是,它与解释器并不完全一致,因为int('---1')
给出了错误,但我的解决方案使用相同的输入返回True
。因此,它不适用于所有可能的输入,但如果您可以排除这些输入,那么这是一个不错的单行检查,如果 x 不是整数并且 < code>True 如果 x 是整数。 但是,如果您确实想要完全模拟内置
int()
的行为,那么最好使用try/ except。不知道是不是pythonic,不过就一行,代码的作用也比较清楚。
*我并不是说解释器忽略前导减号,只是任何数量的前导减号都不会改变结果是整数。
int(--1)
实际上被解释为-(-1)
,或 1。int(---1)
被解释为-(-(-1))
,或-1。 因此,偶数个前导减号给出正整数,奇数个减号给出负整数,但结果始终是整数。I do this all the time b/c I have a mild but admittedly irrational aversion to using the try/except pattern. I use this:
It doesn't accommodate negative numbers, so you could strip out all minus signs on the left side, and then check if the result comprises digits from 0-9:
You could also pass x to str() if you're not sure the input is a string:
There are some (edge?) cases where this falls apart:
type(1E2)
gives<class 'float'>
whereastype(10^2)
gives<class 'int'>
.type(---1)
returns<class int>
. However, it isn't completely consistent with the interpreter in thatint('---1')
gives an error, but my solution returnsTrue
with the same input.So it won't work for every possible input, but if you can exclude those, it's an OK one-line check that returns
False
if x is not an integer andTrue
if x is an integer. But if you really want behavior that exactly models theint()
built-in, you're better off using try/except.I don't know if it's pythonic, but it's one line, and it's relatively clear what the code does.
*I don't mean to say that the interpreter ignores leading minus signs, just that any number of leading minus signs does not change that the result is an integer.
int(--1)
is actually interpreted as-(-1)
, or 1.int(---1)
is interpreted as-(-(-1))
, or -1. So an even number of leading minus signs gives a positive integer, and an odd number of minus signs gives a negative integer, but the result is always an integer.最简单的方法,我用的
The easiest way, which I use
可以用下面的方法来检查。
Can use the below method to check.
Greg Hewgill 的方法缺少一些组件:前导“^”仅匹配字符串的开头,并预先编译 re。 但这种方法将允许您避免 try: except:
我很感兴趣为什么您要尝试避免 try: except?
Greg Hewgill's approach was missing a few components: the leading "^" to only match the start of the string, and compiling the re beforehand. But this approach will allow you to avoid a try: exept:
I would be interested why you are trying to avoid try: except?
我认为
最好重写为:
因为 s[1:] 也会创建一个新字符串
但更好的解决方案是
I think
would be better to rewrite to:
because s[1:] also creates a new string
But much better solution is
前提条件:
int()
的行为对我们来说是一个标准(有时很奇怪:“-00”是它的正确输入)简短回答:
使用以下代码。 它简单、正确(虽然该线程中的许多变体并非如此)并且几乎两倍于
try/ except 和
regex
变体。TL;DR 答案:
我测试了 3 个主要变体 (1) try/ except、(2) re.match() 和 (3) 字符串操作(见上文)。 第三种变体比
try/ except
和re.match()
快大约两倍。 顺便说一句:正则表达式变体是最慢的! 请参阅下面的测试脚本。输出为:
Preconditions:
int()
is a standard for us (sometimes it's strange: "-00" is correct input for it)Short answer:
Use the following code. It is simple, correct (while many variants in this thread aren't) and nearly twice outperforms both
try/except
andregex
variants.TL;DR answer:
I've tested 3 main variants (1) try/except, (2) re.match() and (3) string operations (see above). The third variant is about twice faster then both
try/except
andre.match()
. BTW: regex variant is the slowest! See test script below.Output was:
我真的很喜欢 Shavais 的帖子,但我又添加了一个测试用例(以及内置的 isdigit() 函数):
它明显一致地击败了其余的时间:
使用正常的 2.7 python:
我添加的两个测试用例( isInt_loop 和 isInt_digit)通过了完全相同的测试用例(它们都只接受无符号整数),但我认为人们可以更聪明地修改字符串实现(isInt_loop)而不是内置的 isdigit() 函数,所以我将其包含在内,尽管执行时间略有不同。 (这两种方法都击败了其他所有方法,但不处理额外的东西:“./+/-”)
此外,我确实发现有趣的是,正则表达式(isInt_re2方法)击败了字符串比较Shavais 在 2012 年(目前是 2018 年)进行了相同的测试。 也许正则表达式库已得到改进?
I really liked Shavais' post, but I added one more test case ( & the built in isdigit() function):
and it significantly consistently beats the times of the rest:
using normal 2.7 python:
Both the two test cases I added (isInt_loop and isInt_digit) pass the exact same test cases (they both only accept unsigned integers), but I thought that people could be more clever with modifying the string implementation (isInt_loop) opposed to the built in isdigit() function, so I included it, even though there's a slight difference in execution time. (and both methods beat everything else by a lot, but don't handle the extra stuff: "./+/-" )
Also, I did find it interesting to note that the regex (isInt_re2 method) beat the string comparison in the same test that was performed by Shavais in 2012 (currently 2018). Maybe the regex libraries have been improved?
在我看来,这可能是最直接、最 Pythonic 的方法。 我没有看到这个解决方案,它与正则表达式基本相同,但没有正则表达式。
This is probably the most straightforward and pythonic way to approach it in my opinion. I didn't see this solution and it's basically the same as the regex one, but without the regex.
如果您只想接受较低的 ASCII 数字,请执行以下测试:
Python 3.7+:
(u.isdecimal() 和 u.isascii())
< strong>Python <= 3.6:
(u.isdecimal() and u == str(int(u)))
其他答案建议使用
.isdigit() 或
.isdecimal()
但这些 两者都包含一些大写 unicode 字符,例如'٢'
(u'\u0662'
):If you want to accept lower-ascii digits only, here are tests to do so:
Python 3.7+:
(u.isdecimal() and u.isascii())
Python <= 3.6:
(u.isdecimal() and u == str(int(u)))
Other answers suggest using
.isdigit()
or.isdecimal()
but these both include some upper-unicode characters such as'٢'
(u'\u0662'
):我有一种可能性根本不使用 int,并且不应该引发异常,除非字符串不代表数字
它应该适用于 float 接受的任何类型的字符串,正数,负数,工程符号......
I have one possibility that doesn't use int at all, and should not raise an exception unless the string does not represent a number
It should work for any kind of string that float accepts, positive, negative, engineering notation...
这是一个解析时不会引发错误的函数。 它处理明显的情况,失败时返回
None
(在 CPython 上默认处理最多 2000 个“-/+”符号!):一些测试:
结果:
根据您的需要,您可以使用:
Here is a function that parses without raising errors. It handles obvious cases returns
None
on failure (handles up to 2000 '-/+' signs by default on CPython!):Some tests:
Results:
For your needs you can use:
检查是否为整数后将值转换为字符串,然后检查字符串第一个字符值是
-
或+
以及字符串的其余部分isdigit
。 最后只需检查isdigit
。测试 = ['1', '12015', '1..2', 'a2kk78', '1.5', 2, 1.24, '-8.5', '+88751.71', '-1', '+ 7']
检查
结果
Cast value to string after checking is integer, then check string first character value is
-
or+
and rest of stringisdigit
. Finally just checkisdigit
.test = ['1', '12015', '1..2', 'a2kk78', '1.5', 2, 1.24, '-8.5', '+88751.71', '-1', '+7']
Check
Result
我建议如下:
来自文档:
我应该注意到,当针对不构成 Python 文字的任何内容进行调用时,这将引发 ValueError 异常。 由于问题要求不带 try/ except 的解决方案,因此我有一个 Kobayashi-Maru 类型的解决方案:
¯\_(ツ)_/¯
I suggest the following:
From the docs:
I should note that this will raise a
ValueError
exception when called against anything that does not constitute a Python literal. Since the question asked for a solution without try/except, I have a Kobayashi-Maru type solution for that:¯\_(ツ)_/¯
据我了解,您想检查 int 中的字符串可转换性。 为此,您可以:
PS 您可以轻松修改此 def 以检查浮点数中的字符串可转换性,只需添加 Replace('.', '') 并检查一个 '.' 使用 value.count('.') = 1 存在。
As I understand you want to check string convertability in int. To do that you can:
P.S. You can easy modify this def for checking string convertability in float, just add replace('.', '') and check one '.' existance using value.count('.') = 1.
我想这个问题与速度有关,因为 try/ except 有时间损失:
测试数据
首先,我创建了一个包含 200 个字符串、100 个失败字符串和 100 个数字字符串的列表。
numpy 解决方案(仅适用于数组和 unicode)
np.core.defchararray.isnumeric 也可以使用 unicode 字符串
np.core.defchararray.isnumeric(u'+12')
但它返回和大批。 因此,如果您必须进行数千次转换并且缺少数据或非数字数据,那么这是一个很好的解决方案。try/ except
似乎 numpy 解决方案要快得多。
I guess the question is related with speed since the try/except has a time penalty:
test data
First, I created a list of 200 strings, 100 failing strings and 100 numeric strings.
numpy solution (only works with arrays and unicode)
np.core.defchararray.isnumeric can also work with unicode strings
np.core.defchararray.isnumeric(u'+12')
but it returns and array. So, it's a good solution if you have to do thousands of conversions and have missing data or non numeric data.try/except
Seems that numpy solution is much faster.
呃..试试这个:
如果您不输入非数字的字符串,则此方法有效。
而且(我忘了放数字检查部分。),有一个函数检查字符串是否是数字。 它是str.isdigit()。 下面是一个示例:
如果调用 a.isdigit(),它将返回 True。
Uh.. Try this:
This works if you don't put a string that's not a number.
And also (I forgot to put the number check part. ), there is a function checking if the string is a number or not. It is str.isdigit(). Here's an example:
If you call a.isdigit(), it will return True.
对于正整数,您可以使用
.isdigit
:它不适用于负整数。 假设您可以尝试以下操作:
它不适用于
'16.0'
格式,在这个意义上类似于int
转换。编辑:
with positive integers you could use
.isdigit
:it doesn't work with negative integers though. suppose you could try the following:
it won't work with
'16.0'
format, which is similar toint
casting in this sense.edit: