문제

숫자 인수를 취하는 Python 함수가 있습니다. ~ 해야 하다 올바르게 작동하려면 정수여야 합니다.Python에서 이를 확인하는 가장 좋은 방법은 무엇입니까?

나의 첫 번째 반응은 다음과 같은 작업을 수행하는 것입니다.

def isInteger(n):
    return int(n) == n

그러나 나는 이것이 1) 비용이 많이 들고, 2) 추악하고, 3) 기계 엡실론의 부드러운 자비를 받는다고 생각하지 않을 수 없습니다.

Python은 변수 유형을 검사하는 기본 수단을 제공합니까?아니면 이것이 언어의 동적 유형 디자인을 위반하는 것으로 간주됩니까?

편집하다:많은 사람들이 요청했기 때문에 문제의 응용 프로그램은 IPv4 접두사와 함께 작동하여 일반 텍스트 파일에서 데이터를 소싱합니다.입력이 부동 소수점으로 구문 분석되는 경우 해당 레코드는 잘못된 형식으로 간주되어 무시되어야 합니다.

도움이 되었습니까?

해결책

isinstance(n, int)

int의 서브 클래스가 아닌 실제 int인지 확인 해야하는 경우 (일반적으로이를 수행 할 필요는 없습니다) :

type(n) is int

이것:

return int(n) == n

교차 유형 비교가 사실 일 수 있으므로 좋은 생각이 아닙니다. int(3.0)==3.0

다른 팁

네, Evan이 말했듯이 check를 입력하지 마세요.다음 값을 사용해 보세요.

def myintfunction(value):
   """ Please pass an integer """
   return 2 + value

유형 검사가 없습니다.훨씬 더 좋습니다!시도해 보면 어떤 일이 일어나는지 살펴보겠습니다.

>>> myintfunction(5)
7

그것은 정수이기 때문에 작동합니다.흠.텍스트를 사용해 보겠습니다.

>>> myintfunction('text')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in myintfunction
TypeError: unsupported operand type(s) for +: 'int' and 'str'

어쨌든 수행해야 하는 오류인 TypeError가 표시됩니다.발신자가 그것을 잡기를 원한다면 가능합니다.

만약에 타입체크를 했다면 어떻게 하시겠습니까?오류가 표시되나요?따라서 오류가 이미 자동으로 표시되고 있으므로 유형을 확인할 필요가 없습니다.

게다가 유형 검사를 하지 않았기 때문에 함수가 다른 유형과 함께 작동하게 됩니다.

수레:

>>> print myintfunction(2.2)
4.2

복소수:

>>> print myintfunction(5j)
(2+5j)

소수점:

>>> import decimal
>>> myintfunction(decimal.Decimal('15'))
Decimal("17")

심지어 숫자를 더할 수 있는 완전히 임의적인 객체도 있습니다!

>>> class MyAdderClass(object):
...     def __radd__(self, value):
...             print 'got some value: ', value
...             return 25
... 
>>> m = MyAdderClass()
>>> print myintfunction(m)
got some value:  2
25

따라서 유형 검사를 통해 아무것도 얻지 못하는 것이 분명합니다.그리고 많이 잃습니다.


업데이트:

질문을 편집했으므로 이제 애플리케이션이 int로만 의미가 있는 일부 업스트림 루틴을 호출한다는 것이 분명해졌습니다.

그렇다면 여전히 매개변수를 전달해야 한다고 생각합니다. 받은 업스트림 기능에.업스트림 기능은 이를 올바르게 처리합니다.필요한 경우 오류를 발생시킵니다.나는 매우 의심하다 IP를 처리하는 함수는 부동 소수점을 전달하면 이상하게 동작합니다.도서관 이름을 알려주시면 확인해 드리겠습니다.

하지만...업스트림 함수가 잘못 작동하고 부동 소수점을 전달하면 일부 어린이가 죽는 경우(여전히 의심스럽습니다) 그냥 호출하세요. int() 그 위에:

def myintfunction(value):
   """ Please pass an integer """
   return upstreamfunction(int(value))

아직 유형 검사를 하지 않고 있으므로 유형 검사를 하지 않음으로써 대부분의 이점을 얻을 수 있습니다.


그럼에도 불구하고 응용프로그램의 가독성과 성능이 저하됨에도 불구하고 정말로 입력 확인을 하고 싶다면 다음을 사용하세요. assert 그것을하기 위해.

assert isinstance(...)
assert type() is xxxx

그래야 우리가 꺼질 수 있어 asserts 그리고 이것을 제거하십시오 <sarcasm>특징</sarcasm> 프로그램에서 다음과 같이 호출하여

python -OO program.py
if type(n) is int

이것은 다음을 확인합니다 n 파이썬 int입니다 int. 서브 클래스를 허용하지 않습니다 int.

그러나 유형 검사는 "파이썬 웨이"에 맞지 않습니다. 당신은 더 잘 사용합니다 n int로서, 그리고 그것이 예외를 던지면 그것을 잡아서 행동하십시오.

파이썬은 이제 지원합니다 점진적인 타이핑 TH를 통해 입력 모듈 그리고 Mypy. 그만큼 typing 모듈은 Python 3.5의 STDLIB의 일부이며 다운로드 할 수 있습니다. PYPI에서 Python 2 또는 이전 버전의 Python 3에 대한 백 포트가 필요한 경우 설치할 수 있습니다. mypy 달리면서 pip install mypy 명령 줄에서.

요컨대, 일부 함수가 int, float 및 문자열을 반환하는지 확인하려면 다음과 같이 기능을 주석을 달 것입니다.

def foo(param1: int, param2: float) -> str:
    return "testing {0} {1}".format(param1, param2)

파일이 명명 된 경우 test.py, 실행하여 mypy를 설치하면 typecheck 할 수 있습니다. mypy test.py 명령 줄에서.

기능 주석을 지원하지 않고 이전 버전의 Python을 사용하는 경우 유형 주석을 사용하여 동일한 효과를 달성 할 수 있습니다.

def foo(param1, param2):
    # type: (int, float) -> str
    return "testing {0} {1}".format(param1, param2)

동일한 명령을 사용합니다 mypy test.py Python 3 파일의 경우 mypy --py2 test.py Python 2 파일의 경우.

유형 주석은 런타임시 Python 통역사에 의해 전적으로 무시되므로 오버 헤드가 최소화되지 않습니다. 일반적인 워크 플로우는 코드에서 작업하고 주기적으로 실수와 오류를 잡는 것입니다. Pycharm과 같은 일부 IDE는 유형 힌트를 이해하고 직접 편집하는 동안 코드에서 문제와 유형의 불일치를 경고 할 수 있습니다.

어떤 이유로 든 런타임에 유형을 확인 해야하는 경우 (아마도 많은 입력을 확인해야합니까?) 다른 답변에 나열된 조언을 따라야합니다. isinstance, issubclass, 같은. 다음과 같은 라이브러리도 있습니다 억지로 시키다 런타임에서 타이 테크 킹 (유형 주석을 존중)을 수행하려는 시도이지만, 글쓰기의 시간이 얼마나되는지는 확실하지 않습니다.

자세한 내용과 세부 사항은 다음을 참조하십시오 Mypy 웹 사이트,, Mypy FAQ, 그리고 PEP 484.

확인하지 마십시오. 오리 타이핑의 요점은 당신이 할 필요가 없다는 것입니다. 예를 들어, 누군가가 다음과 같은 일을한다면 어떨까요?

class MyInt(int):
    # ... extra stuff ...

파이썬으로 프로그래밍하고 다른 언어에서와 같이 타이핑을 수행하는 것은 스크루 드라이버를 선택하여 못을 박는 것처럼 보입니다. Python의 예외 처리 기능을 사용하는 것이 더 우아합니다.

대화식 명령 줄에서 다음과 같은 문장을 실행할 수 있습니다.

int('sometext')

오류가 발생할 것입니다 -Ipython은 다음과 같이 말합니다.

<type 'exceptions.ValueError'>: invalid literal for int() with base 10: 'sometext'

이제 다음과 같은 코드를 작성할 수 있습니다.

try:
   int(myvar) + 50
except ValueError:
   print "Not a number"

이는 필요한 작업을 수행하고 예상되는 오류를 포착하기 위해 사용자 정의 할 수 있습니다. 약간 복잡해 보이지만 파이썬의 구문과 관용구에 적합하며 매우 읽기 쉬운 코드 (파이썬을 사용하는 데 익숙해지면)를 초래합니다.

나는 다음과 같은 것을 유혹 할 것입니다.

def check_and_convert(x):
    x = int(x)
    assert 0 <= x <= 255, "must be between 0 and 255 (inclusive)"
    return x

class IPv4(object):
    """IPv4 CIDR prefixes is A.B.C.D/E where A-D are 
       integers in the range 0-255, and E is an int 
       in the range 0-32."""

    def __init__(self, a, b, c, d, e=0):
        self.a = check_and_convert(a)
        self.b = check_and_convert(a)
        self.c = check_and_convert(a)
        self.d = check_and_convert(a)
        assert 0 <= x <= 32, "must be between 0 and 32 (inclusive)"
        self.e = int(e)

그렇게 사용할 때는 무엇이든 전달할 수 있지만 유효한 정수 만 저장할 수 있습니다.

어때요 :

def ip(string):
    subs = string.split('.')
    if len(subs) != 4:
        raise ValueError("incorrect input")
    out = tuple(int(v) for v in subs if 0 <= int(v) <= 255)
    if len(out) != 4:
        raise ValueError("incorrect input")
    return out

물론 표준 isinstance (3, int) 함수가 있습니다 ...

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top