여부를 알 수있는 방법이 있나요 문자열 (예를 들어, 정수를 나타내고 '3'
, '-17'
하지만 '3.14'
나 'asfasfas'
메커니즘을 제외 / 시도를 사용하지 않고)는?
is_int('3.14') = False
is_int('-7') = True
여부를 알 수있는 방법이 있나요 문자열 (예를 들어, 정수를 나타내고 '3'
, '-17'
하지만 '3.14'
나 'asfasfas'
메커니즘을 제외 / 시도를 사용하지 않고)는?
is_int('3.14') = False
is_int('-7') = True
답변:
try/except
s 를 사용하는 것이 정말 짜증나는 경우 도우미 함수를 작성하십시오.
def RepresentsInt(s):
try:
int(s)
return True
except ValueError:
return False
>>> print RepresentsInt("+123")
True
>>> print RepresentsInt("10.0")
False
파이썬이 정수로 간주하는 모든 문자열을 정확하게 다루기 위해 더 많은 코드가 될 것입니다. 나는 이것에 대해 pythonic이라고 말합니다.
>>> print RepresentsInt(10.0)
True
>>> print RepresentsInt(10.06)
True
양의 정수로 다음을 사용할 수 있습니다 .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()
u'²'.isdigit()
true이지만 int(u'²')
ValueError가 발생합니다. u.isdecimal()
대신 사용하십시오 . str.isdigit()
파이썬 2에서 로케일에 의존합니다.
check_int('')
반환하는 대신 예외를 제기합니다False
시도 / 제외가 어떤 이유로 든 잘 수행되지 않는 것을 발견했습니다 (그리고 이것을 반복해서 테스트했습니다). 나는 종종 여러 가지 일을 시도하고, 시도 / 제외를 사용하여 테스트 된 것 중 가장 좋은 것을 수행하는 방법을 찾지 못했다고 생각합니다. 실제로 그 방법은 일반적으로 최악이 아니라면 최악입니다. 모든 경우가 아니라 많은 경우에 해당됩니다. 나는 많은 사람들이 그것이 "Pythonic"방식이라고 말하지만, 그것은 내가 그들과 함께하는 하나의 영역입니다. 나에게 그것은 성능이 우수하지도 않고 우아하지도 않으므로 오류 트래핑 및보고에만 사용하는 경향이 있습니다.
PHP, perl, ruby, C 및 심지어 괴물 껍질조차도 문자열을 정수로 테스트하는 간단한 기능을 가지고 있지만 그 가정을 검증하는 데 상당한주의를 기울여 나를 혼란스럽게 만들었습니다! 분명히이 부족은 흔한 질병입니다.
Bruno의 게시물에 대한 빠르고 더러운 편집은 다음과 같습니다.
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 방법이 올바른 일이라고 생각합니다.
편집하다:
파이썬 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를 반환합니다. 독을 골라 봐
try
isInt_try : 0.6552 / isInt_str : 0.6396 / isInt_re : 1.0296 / isInt_re2 : 0.5168가 더 효율적입니다.
str.isdigit()
트릭을해야합니다.
예 :
str.isdigit("23") ## True
str.isdigit("abc") ## False
str.isdigit("23.4") ## False
편집 : @BuzzMoschetti가 지적 했듯이이 방법은 마이너스 숫자 (예 : "-23" )에 실패합니다 . 경우 귀하의 input_num이 덜 0보다 수 있으며, 사용 의 re.sub (regex_search 공히, regex_replace, 내용) 적용하기 전에 str.isdigit을 () . 예를 들면 다음과 같습니다.
import re
input_num = "-23"
input_num = re.sub("^-", "", input_num) ## "^" indicates to remove the first "-" only
str.isdigit(input_num) ## True
정규식을 사용하십시오.
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()
.
적절한 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
>>> "+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()
Greg Hewgill의 접근 방식에는 몇 가지 구성 요소가 누락되었습니다. 문자열의 시작 부분에만 일치하는 선행 "^"및 사전 컴파일. 그러나이 방법을 사용하면 시도를 피할 수 있습니다.
import re
INT_RE = re.compile(r"^[-]?\d+$")
def RepresentsInt(s):
return INT_RE.match(str(s)) is not None
나는 당신이 시도를 피하려고하는 이유에 관심이있을 것입니다 : 제외?
나는 항상이 작업을 수행해야하며 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)])
이것이 분리되는 경우가 적어도 두 가지 (가장자리?) 있습니다.
type(1E2)
주는 <class 'float'>
반면 type(10^2)
제공하기 때문에 의견이 일치하지 않습니다 <class 'int'>
.따라서 가능한 모든 입력에 대해 작동 하지는 않지만 과학 표기법, 지수 표기법 및 빈 문자열을 제외 할 수 False
있으면 x가 정수가 아니고 x가 정수인지 를 반환하는 OK 한 줄 검사입니다 True
.
파이썬이 아닌지 모르겠지만 한 줄이며 코드의 기능이 상대적으로 명확합니다.
all(xi in '1234567890' for xi in x])
패턴은 잔디밭을 걸을 수있는 허가를 요구하는 것처럼 보입니다. 나는 허가를받는 사람이되어서 기쁘지 않지만 여기 있습니다.
나는 생각한다
s.startswith('-') and s[1:].isdigit()
다시 작성하는 것이 좋습니다.
s.replace('-', '').isdigit()
s [1 :]도 새로운 문자열을 생성하기 때문에
그러나 훨씬 더 나은 해결책은
s.lstrip('+-').isdigit()
replace
합니까? 또한 5-2
예를 들어 잘못 받아 들입니다.
s='-'
나는 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 --version
Python 2.7.10
내가 추가 한 두 테스트 사례 (isInt_loop 및 isInt_digit)는 모두 동일한 테스트 사례를 통과하지만 (모두 부호없는 정수만 허용 함) 내장 isdigit과 반대로 문자열 구현 (isInt_loop)을 수정하면 사람들이 더 영리 할 수 있다고 생각했습니다. () 함수이므로 실행 시간에 약간의 차이가 있지만 포함 시켰습니다. (두 방법 모두 다른 모든 것을 능가하지만 여분의 것을 처리하지 마십시오 : "./+/-")
또한 정규식 (isInt_re2 방법)이 2012 년 (현재 2018) Shavais가 수행 한 것과 동일한 테스트에서 문자열 비교를 능가한다는 점에 주목하는 것이 흥미로 웠습니다. 정규식 라이브러리가 개선되었을 수 있습니까?
다음은 오류를 발생시키지 않고 구문 분석하는 함수입니다. 명백한 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
나는 다음을 제안한다.
import ast
def is_int(s):
return isinstance(ast.literal_eval(s), int)
로부터 문서 :
파이썬 리터럴 또는 컨테이너 디스플레이를 포함하는 표현식 노드 또는 문자열을 안전하게 평가하십시오. 제공된 문자열 또는 노드는 문자열, 바이트, 숫자, 튜플, 목록, dicts, set, booleans 및 None과 같은 Python 리터럴 구조로만 구성 될 수 있습니다.
ValueError
파이썬 리터럴을 구성하지 않는 것에 대해 호출 하면 예외가 발생합니다. 질문은 시도 / 제외가없는 솔루션을 요구했기 때문에 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
¯ \ _ (ツ) _ / ¯
시도 / 제외에는 시간 패널티가 있으므로 질문이 속도와 관련이 있다고 생각합니다.
먼저 200 개의 문자열, 100 개의 실패 문자열 및 100 개의 숫자 문자열 목록을 만들었습니다.
from random import shuffle
numbers = [u'+1'] * 100
nonumbers = [u'1abc'] * 100
testlist = numbers + nonumbers
shuffle(testlist)
testlist = np.array(testlist)
np.core.defchararray.isnumeric은 유니 코드 문자열에도 사용할 수 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 솔루션이 훨씬 빠릅니다.
낮은 ASCII 숫자 만 허용하려면 다음을 수행하십시오.
파이썬 3.7 이상 : (u.isdecimal() and u.isascii())
파이썬 <= 3.6 : (u.isdecimal() and u == str(int(u)))
다른 답변은 .isdigit()
또는을 사용하는 것이 .isdecimal()
좋지만 둘 다'٢'
( u'\u0662'
) 와 같은 일부 상위 유니 코드 문자를 포함합니다 .
u = u'\u0662' # '٢'
u.isdigit() # True
u.isdecimal() # True
u.isascii() # False (Python 3.7+ only)
u == str(int(u)) # False
int()
.
어 .. 이것을 시도하십시오 :
def int_check(a):
if int(a) == a:
return True
else:
return False
숫자가 아닌 문자열을 넣지 않으면 작동합니다.
또한 (숫자 확인 부분을 잊어 버렸습니다.), 문자열이 숫자인지 여부를 확인하는 기능이 있습니다. str.isdigit ()입니다. 예를 들면 다음과 같습니다.
a = 2
a.isdigit()
a.isdigit ()를 호출하면 True를 반환합니다.
2
할당 된 값 주위에 따옴표가 필요하다고 생각합니다 a
.