[python] 문자열이 숫자 (부동)인지 어떻게 확인합니까?

파이썬에서 문자열을 숫자로 나타낼 수 있는지 확인하는 가장 좋은 방법은 무엇입니까?

현재 내가 가지고있는 기능은 다음과 같습니다.

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

추악하고 느릴뿐만 아니라 어색한 것 같습니다. 그러나 float주 함수를 호출하는 것이 더 나쁘기 때문에 더 좋은 방법을 찾지 못했습니다 .



답변

추악하고 느릴뿐만 아니라

나는 둘 다 논쟁 할 것이다.

정규식이나 다른 문자열 구문 분석 방법은 더 느리고 느립니다.

위의 것보다 많은 것이 빠를 지 확실하지 않습니다. 함수를 호출하고 반환합니다. 스택 프레임을 광범위하게 검색하지 않고 가장 일반적인 예외가 발생하기 때문에 Try / Catch는 많은 오버 헤드를 발생시키지 않습니다.

문제는 모든 숫자 변환 함수에 두 가지 종류의 결과가 있다는 것입니다

  • 숫자가 유효하면 숫자
  • 유효한 번호를 구문 분석 할 수 없음을 표시하는 상태 코드 (예 : errno를 통한) 또는 예외입니다.

예를 들어 C는 여러 가지 방법으로 해킹합니다. 파이썬은 그것을 명확하고 명시 적으로 설명합니다.

이 작업을 수행하는 코드가 완벽하다고 생각합니다.


답변

부동 소수점 대신 (양수, 부호없는) 정수를 파싱하려는 경우 isdigit()문자열 객체에 함수를 사용할 수 있습니다 .

>>> a = "03523"
>>> a.isdigit()
True
>>> b = "963spam"
>>> b.isdigit()
False

문자열 메소드- isdigit(): Python2 , Python3

유니 코드 문자열에는 유니 코드에 익숙하지 않은 것도 있습니다.
십진수 / 십진수입니다


답변

TL; DR 가장 좋은 해결책은s.replace('.','',1).isdigit()

나는 어떤 한 벤치 마크 다른 접근 방법을 비교하는

def is_number_tryexcept(s):
    """ Returns True is string is a number. """
    try:
        float(s)
        return True
    except ValueError:
        return False

import re
def is_number_regex(s):
    """ Returns True is string is a number. """
    if re.match("^\d+?\.\d+?$", s) is None:
        return s.isdigit()
    return True


def is_number_repl_isdigit(s):
    """ Returns True is string is a number. """
    return s.replace('.','',1).isdigit()

문자열이 숫자가 아닌 경우 except-block은 상당히 느립니다. 그러나 더 중요한 것은 try-except 방법이 과학적 표기법을 올바르게 처리하는 유일한 방법입니다.

funcs = [
          is_number_tryexcept,
          is_number_regex,
          is_number_repl_isdigit
          ]

a_float = '.1234'

print('Float notation ".1234" is not supported by:')
for f in funcs:
    if not f(a_float):
        print('\t -', f.__name__)

플로트 표기법 “.1234″는 다음에서 지원되지 않습니다.
-is_number_regex

scientific1 = '1.000000e+50'
scientific2 = '1e50'


print('Scientific notation "1.000000e+50" is not supported by:')
for f in funcs:
    if not f(scientific1):
        print('\t -', f.__name__)




print('Scientific notation "1e50" is not supported by:')
for f in funcs:
    if not f(scientific2):
        print('\t -', f.__name__)

과학 표기법 “1.000000e + 50″은 다음에서 지원하지 않습니다.
-is_number_regex
-is_number_repl_isdigit
과학 표기법 “1e50″은 다음에서 지원하지 않습니다.
-is_number_regex
-is_number_repl_isdigit

편집 : 벤치 마크 결과

import timeit

test_cases = ['1.12345', '1.12.345', 'abc12345', '12345']
times_n = {f.__name__:[] for f in funcs}

for t in test_cases:
    for f in funcs:
        f = f.__name__
        times_n[f].append(min(timeit.Timer('%s(t)' %f,
                      'from __main__ import %s, t' %f)
                              .repeat(repeat=3, number=1000000)))

다음 기능들이 테스트 된 곳

from re import match as re_match
from re import compile as re_compile

def is_number_tryexcept(s):
    """ Returns True is string is a number. """
    try:
        float(s)
        return True
    except ValueError:
        return False

def is_number_regex(s):
    """ Returns True is string is a number. """
    if re_match("^\d+?\.\d+?$", s) is None:
        return s.isdigit()
    return True


comp = re_compile("^\d+?\.\d+?$")

def compiled_regex(s):
    """ Returns True is string is a number. """
    if comp.match(s) is None:
        return s.isdigit()
    return True


def is_number_repl_isdigit(s):
    """ Returns True is string is a number. """
    return s.replace('.','',1).isdigit()

여기에 이미지 설명을 입력하십시오


답변

고려해야 할 한 가지 예외가 있습니다 : 문자열 ‘NaN’

is_number가 ‘NaN’에 대해 FALSE를 반환하도록하려면 Python이 숫자가 아닌 숫자의 표현으로 변환 할 때이 코드가 작동하지 않습니다 (ID 문제에 대한 대화).

>>> float('NaN')
nan

그렇지 않으면 실제로 광범위하게 사용하는 코드에 대해 실제로 감사드립니다. 🙂

지.


답변

이건 어때요:

'3.14'.replace('.','',1).isdigit()

‘.’가 없거나없는 경우에만 true를 반환합니다. 자릿수로.

'3.14.5'.replace('.','',1).isdigit()

거짓을 반환합니다

편집 : 방금 다른 의견을 보았습니다 … .replace(badstuff,'',maxnum_badstuff)다른 경우에 대해 추가 할 수 있습니다. 임의의 조미료가 아닌 소금을 통과하면 ( xkcd # 974 ) 이것이 잘됩니다. : P


답변

추악하고 느릴뿐만 아니라 어색한 것 같습니다.

익숙해지는 데 다소 시간이 걸릴 수 있지만 이것은 파이썬을 사용하는 방법입니다. 이미 지적했듯이 대안은 더 나쁩니다. 그러나 이런 식으로 일을하는 것의 또 다른 장점은 다형성입니다.

오리 타이핑의 기본 개념은 “걸 으면서 오리처럼 말하면 오리입니다.” 플로트로 변환 할 수 있는지 확인하는 방법을 변경할 수 있도록 문자열을 서브 클래스 화해야한다면 어떻게해야합니까? 아니면 다른 물체를 완전히 테스트하기로 결정한 경우 어떻게해야합니까? 위의 코드를 변경하지 않고도 이러한 작업을 수행 할 수 있습니다.

다른 언어는 인터페이스를 사용하여 이러한 문제를 해결합니다. 다른 스레드에 어떤 솔루션이 더 나은지 분석을 저장하겠습니다. 그러나 요점은 파이썬이 결정의 오리 타이핑 측면에 결정적이라는 것입니다. 파이썬에서 많은 프로그래밍을 할 계획이라면 아마도 이와 같은 구문에 익숙해 져야 할 것입니다 (그러나 이것이 의미는 아닙니다 물론 좋아해야합니다).

고려해야 할 또 다른 사항 : 파이썬은 다른 많은 언어 (예 : .Net보다 30 배 빠름)에 비해 예외를 던지고 잡는 데 매우 빠릅니다. 심지어 언어 자체는 예외가 아닌 예외적 인 정상적인 프로그램 조건을 전달하기 위해 예외를 발생시킵니다 (for 루프를 사용할 때마다). 따라서 중요한 문제가 발견 될 때 까지이 코드의 성능 측면에 대해 너무 걱정하지 않아도됩니다.


답변

Alfe가 지적한 후에 업데이트되었으므로 복잡한 핸들로 플로트를 별도로 확인할 필요가 없습니다.

def is_number(s):
    try:
        complex(s) # for int, long, float and complex
    except ValueError:
        return False

    return True

이전에 말했다 : 드문 경우이지만 float로 표현 할 수없는 복잡한 숫자 (예 : 1 + 2i)를 확인해야 할 수도 있습니다.

def is_number(s):
    try:
        float(s) # for int, long and float
    except ValueError:
        try:
            complex(s) # for complex
        except ValueError:
            return False

    return True