주어진 객체가 주어진 유형인지 확인하는 가장 좋은 방법은 무엇입니까? 객체가 주어진 유형에서 상속되는지 여부를 확인하는 것은 어떻습니까?
o
가 있다고 가정해 봅시다. str
인지 어떻게 확인합니까?
질문자 :Herge
주어진 객체가 주어진 유형인지 확인하는 가장 좋은 방법은 무엇입니까? 객체가 주어진 유형에서 상속되는지 여부를 확인하는 것은 어떻습니까?
o
가 있다고 가정해 봅시다. str
인지 어떻게 확인합니까?
있는지 확인하려면 o
의 인스턴스 str
또는 서브 클래스 str
, 사용 isinstance은 (이것은 "표준"방법이 될 것이다)
if isinstance(o, str):
o
유형이 정확히 str
인지 확인하려면(서브클래스 제외):
if type(o) is str:
다음도 작동하며 경우에 따라 유용할 수 있습니다.
if issubclass(type(o), str):
관련 정보는 Python 라이브러리 참조의 내장 함수를 참조하십시오.
참고 사항: 이 경우 Python 2를 사용하는 경우 실제로 다음을 사용할 수 있습니다.
if isinstance(o, basestring):
이것은 유니코드 문자열도 잡을 것이기 때문입니다( unicode
str
의 하위 클래스가 아닙니다. str
과 unicode
basestring
하위 클래스입니다). 문자열( str
)과 이진 데이터( bytes
) 가 엄격하게 분리 basestring
더 이상 존재하지 않습니다.
또는 isinstance
는 클래스의 튜플을 허용합니다. o
(str, unicode)
중 하나의 하위 클래스 인스턴스인 경우 True
를 반환합니다.
if isinstance(o, (str, unicode)):
객체의 유형을 확인하는 가장 Pythonic한 방법은... 확인하지 않는 것입니다.
Python은 Duck Typing을 권장하므로 개체의 메서드를 원하는 방식으로 사용하는 try...except
는 시도해야 합니다. 따라서 함수가 쓰기 가능한 파일 객체를 찾고 있다면 file
의 하위 클래스인지 확인 하지 말고 .write()
메서드를 사용하십시오!
물론 때때로 이러한 멋진 추상화가 무너지고 isinstance(obj, cls)
가 필요한 것입니다. 그러나 아껴서 사용하십시오.
isinstance(o, str)
o
가 str
str
에서 상속된 유형이면 True
를 반환합니다.
type(o) is str
반환됩니다 True
과 경우에만 경우 o
STR이다. o
str
에서 상속된 유형이면 False
를 반환합니다.
질문을 하고 답변을 받은 후 유형 힌트가 Python에 추가되었습니다 . Python의 유형 힌트를 사용하면 유형을 확인할 수 있지만 정적으로 유형이 지정된 언어와는 매우 다른 방식입니다. Python의 유형 힌트는 예상되는 인수 유형을 함수와 연결된 런타임 액세스 가능한 데이터로 함수와 연결하고 이를 통해 유형을 확인할 수 있습니다. 유형 힌트 구문의 예:
def foo(i: int): return i foo(5) foo('oops')
이 경우 인수의 주석 유형이 int
foo('oops')
에 대해 오류가 트리거되기를 원합니다. 추가 된 타입 힌트는 스크립트가 정상적으로 실행시 오류가 발생하지 않습니다. 그러나 다른 프로그램이 쿼리하고 유형 오류를 확인하는 데 사용할 수 있는 예상 유형을 설명하는 속성을 함수에 추가합니다.
유형 오류를 찾는 데 사용할 수 있는 다른 프로그램 중 하나는 mypy
.
mypy script.py script.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "int"
mypy
를 설치해야 할 수도 있습니다. CPython과 함께 제공되지는 않지만 어느 정도의 "공식성"이 있는 것 같습니다.)
이 방식의 유형 검사는 정적으로 유형이 지정된 컴파일된 언어의 유형 검사와 다릅니다. 유형은 Python에서 동적이기 때문에 유형 검사는 런타임에 수행되어야 하며, 이는 올바른 프로그램에서도 모든 기회에 발생한다고 주장하는 경우 비용을 부과합니다. 명시적 유형 검사는 필요한 것보다 더 제한적일 수 있으며 불필요한 오류를 유발할 수 있습니다(예: 인수가 실제로 정확히 list
유형이어야 합니까? 아니면 반복 가능한 것이 충분한가요?).
명시적 유형 검사의 장점은 오류를 더 일찍 포착할 수 있고 덕 타이핑보다 더 명확한 오류 메시지를 제공할 수 있다는 것입니다. 오리 유형의 정확한 요구 사항은 외부 문서(완벽하고 정확하기를 바랍니다)로만 표현할 수 있으며 호환되지 않는 유형의 오류는 원래 위치에서 멀리 발생할 수 있습니다.
Python의 유형 힌트는 유형을 지정하고 확인할 수 있는 절충안을 제공하기 위한 것이지만 일반적인 코드 실행 중에는 추가 비용이 들지 않습니다.
typing
패키지는 특정 유형을 요구하지 않고 필요한 동작을 표현하기 위해 유형 힌트에 사용할 수 있는 유형 변수를 제공합니다. 예를 들어, Iterable
및 Callable
과 같은 변수가 포함되어 이러한 동작이 있는 모든 유형의 필요성을 지정합니다.
유형 힌트는 유형을 확인하는 가장 Pythonic한 방법이지만 유형을 전혀 확인하지 않고 오리 타이핑에 의존하는 것이 훨씬 더 Pythonic입니다. 유형 힌트는 비교적 새롭고 배심원단은 가장 Pythonic한 솔루션일 때 아직 미정입니다. 비교적 논쟁의 여지가 없지만 매우 일반적인 비교: 유형 힌트는 시행할 수 있는 문서 형식을 제공하고, 코드가 더 일찍 생성되고 오류를 더 쉽게 이해할 수 있도록 하며, 덕 타이핑이 할 수 없는 오류를 포착할 수 있으며, 정적으로(비정상적으로) 확인할 수 있습니다. 의미하지만 여전히 런타임 밖에 있음). 반면에 오리 타이핑은 오랫동안 파이썬적인 방식이었고 정적 타이핑의 인지적 오버헤드를 부과하지 않고 덜 장황하며 실행 가능한 모든 유형과 일부를 수용할 것입니다.
언제 위험한지 모른 채 오리 타이핑이 나쁜 이유는 다음과 같습니다. 예를 들어: 다음은 Python 코드입니다(적절한 들여쓰기 생략 가능). 이 상황은 isinstance 및 issubclassof 함수를 관리하여 오리가 정말로 필요할 때 폭탄을 얻지 않도록 함으로써 피할 수 있습니다.
class Bomb: def __init__(self): "" def talk(self): self.explode() def explode(self): print "BOOM!, The bomb explodes." class Duck: def __init__(self): "" def talk(self): print "I am a duck, I will not blow up if you ask me to talk." class Kid: kids_duck = None def __init__(self): print "Kid comes around a corner and asks you for money so he could buy a duck." def takeDuck(self, duck): self.kids_duck = duck print "The kid accepts the duck, and happily skips along" def doYourThing(self): print "The kid tries to get the duck to talk" self.kids_duck.talk() myKid = Kid() myBomb = Bomb() myKid.takeDuck(myBomb) myKid.doYourThing()
유형의 __name__을 사용하여 변수의 유형을 확인할 수 있습니다.
전:
>>> a = [1,2,3,4] >>> b = 1 >>> type(a).__name__ 'list' >>> type(a).__name__ == 'list' True >>> type(b).__name__ == 'list' False >>> type(b).__name__ 'int'
isinstance(o, str)
Python과 같은 동적 언어를 사용할 때의 멋진 점은 그런 것을 확인할 필요가 없다는 것입니다.
나는 당신의 객체에 필요한 메소드를 호출하고 AttributeError
잡을 것입니다. 나중에 이것은 테스트를 위해 객체를 조롱하는 것과 같은 다른 작업을 수행하기 위해 다른(관련 없어 보이는) 객체와 함께 메서드를 호출할 수 있게 해줍니다.
객체 와 같은 파일 을 반환하는 urllib2.urlopen()
을 사용하여 웹에서 데이터를 가져올 때 이것을 많이 사용했습니다. 이것은 차례로 실제 파일과 read()
메서드를 구현하기 때문에 파일에서 읽는 거의 모든 메서드에 전달할 수 있습니다.
isinstance()
를 사용할 시간과 장소가 있다고 확신합니다. 그렇지 않으면 아마 없을 것입니다 :)
더 복잡한 유형 유효성 검사의 경우 Python 유형 힌트 주석을 기반으로 유효성을 검사하는 typeguard 접근 방식을 좋아합니다.
from typeguard import check_type from typing import List try: check_type('mylist', [1, 2], List[int]) except TypeError as e: print(e)
매우 깨끗하고 읽기 쉬운 방식으로 매우 복잡한 유효성 검사를 수행할 수 있습니다.
check_type('foo', [1, 3.14], List[Union[int, float]]) # vs isinstance(foo, list) and all(isinstance(a, (int, float)) for a in foo)
Python 3.10 에서는 |
에 isinstance
:
>>> isinstance('1223', int | str) True >>> isinstance('abcd', int | str) True
휴고에게:
아마도 array
아니라 list
의미하지만 유형 검사의 전체 문제를 가리킵니다. 문제의 개체가 목록인지 알고 싶지 않고 일종의 시퀀스인지 또는 단일 항목인지 알고 싶습니다. 물체. 따라서 시퀀스처럼 사용하십시오.
기존 시퀀스에 개체를 추가하거나 개체 시퀀스인 경우 모두 추가한다고 가정합니다.
try: my_sequence.extend(o) except TypeError: my_sequence.append(o)
이것에 대한 한 가지 트릭은 문자열 및/또는 문자열 시퀀스로 작업하는 경우입니다. 문자열은 종종 단일 개체로 생각되지만 문자 시퀀스이기도 하므로 까다롭습니다. 그보다 더 나쁜 것은 실제로 단일 길이 문자열의 시퀀스이기 때문입니다.
저는 일반적으로 단일 값이나 시퀀스만 허용하도록 API를 설계하도록 선택합니다. 그러면 작업이 더 쉬워집니다. 필요한 경우 전달할 때 단일 값 주위에 [ ]
를 넣는 것은 어렵지 않습니다.
(이는 문자열이 시퀀스처럼 보이기 때문에 문자열에 오류를 일으킬 수 있습니다.)
수락된 답변은 질문에 대한 답변을 제공한다는 점에서 질문에 대한 답변입니다.
Q: 주어진 객체가 주어진 유형인지 확인하는 가장 좋은 방법은 무엇입니까? 객체가 주어진 유형에서 상속되는지 여부를 확인하는 것은 어떻습니까?
A:
isinstance, issubclass, type
을 사용하여 유형에 따라 확인하십시오.
그러나 다른 답변과 의견에서 빠르게 지적할 수 있듯이 "유형 검사"라는 개념에는 파이썬보다 훨씬 더 많은 것이 있습니다. Python 3 및 유형 힌트 가 추가된 이후로 많은 것이 변경되었습니다. 아래에서 유형 검사, 덕 타이핑 및 예외 처리와 관련된 몇 가지 어려움에 대해 설명합니다. 유형 검사가 필요하지 않다고 생각하는 사람들을 위해(보통 필요하지 않지만 우리는 여기에 있습니다) 유형 힌트를 대신 사용할 수 있는 방법도 지적합니다.
유형 검사가 항상 파이썬에서 적절한 것은 아닙니다. 다음 예를 고려하십시오.
def sum(nums): """Expect an iterable of integers and return the sum.""" result = 0 for n in nums: result += n return result
입력이 정수의 이터러블인지 확인하기 위해 중요한 문제가 발생합니다. 모든 요소가 정수인지 확인하는 유일한 방법은 루프를 통해 각 요소를 확인하는 것입니다. 그러나 전체 반복자를 반복하면 의도한 코드에 대해 아무 것도 남지 않습니다. 이런 상황에서 우리는 두 가지 선택을 할 수 있습니다.
반복하면서 확인합니다.
사전에 확인하되 확인하는 대로 모든 것을 보관하십시오.
옵션 1은 특히 여러 곳에서 유사한 검사를 수행해야 하는 경우 코드를 복잡하게 만드는 단점이 있습니다. 그것은 우리가 코드에서 iterable을 사용하는 모든 곳으로 함수의 상단에서 유형 검사를 이동하도록 강요합니다.
옵션 2는 반복자의 전체 목적을 파괴한다는 명백한 단점이 있습니다. 요점은 데이터를 저장할 필요가 없기 때문에 저장하지 않는 것입니다.
모든 요소를 확인하는 것이 너무 많은지 확인하는 것이 너무 많다고 생각할 수도 있습니다. 그러면 입력 자체가 반복 가능한 유형인지 확인할 수 있지만 실제로는 반복 가능한 기본 클래스가 없습니다. __iter__
구현하는 모든 유형은 반복 가능합니다.
대안적인 접근 방식은 유형 검사를 완전히 포기하고 대신 예외 처리 및 덕 타이핑에 집중하는 것입니다. 즉, try-except 블록으로 코드를 래핑하고 발생하는 모든 오류를 포착합니다. 또는 아무 것도 하지 않고 코드에서 자연스럽게 예외가 발생하도록 하십시오.
예외를 잡는 한 가지 방법이 있습니다.
def sum(nums): """Try to catch exceptions?""" try: result = 0 for n in nums: result += n return result except TypeError as e: print(e)
이전 옵션과 비교하면 확실히 더 좋습니다. 코드를 실행하면서 확인 중입니다. TypeError
가 있다면 우리는 알게 될 것입니다. 입력을 반복하는 모든 곳에 검사를 할 필요가 없습니다. 그리고 반복할 때 입력을 저장할 필요가 없습니다.
또한, 이 접근 방식은 덕 타이핑을 가능하게 합니다. specific types
을 확인하는 대신 specific behaviors
을 확인하고 입력이 예상대로 동작하지 않을 때를 찾는 것으로 이동했습니다(이 경우 nums
n
을 추가할 수 있음).
그러나 예외 처리를 훌륭하게 만드는 정확한 이유도 실패할 수 있습니다.
float
는 int
가 아니지만 작동하기 위한 동작 요구 사항을 충족합니다.
전체 코드를 try-except 블록으로 래핑하는 것도 좋지 않습니다.
처음에는 이러한 문제가 문제처럼 보이지 않을 수 있지만 마음을 바꿀 수 있는 몇 가지 이유가 있습니다.
사용자는 더 이상 함수가 의도한 대로 int
를 반환할 것으로 기대할 수 없습니다. 이것은 다른 곳에서 코드를 깨뜨릴 수 있습니다.
예외는 다양한 소스에서 올 수 있으므로 전체 코드 블록에서 try-except를 사용하면 의도하지 않은 예외가 포착될 수 있습니다. nums
이 반복 가능하고 정수 요소가 있는지 확인하기만 했습니다.
이상적으로는 우리의 코드 생성기에서 예외를 포착하고 그 자리에 더 유익한 예외를 발생시키고 싶습니다. 다른 사람의 코드에서 당신이 작성하지 않은 줄 외에 어떤 설명도 없이 예외가 발생하고 일부 TypeError
발생하면 재미가 없습니다.
위의 사항에 대한 응답으로 예외 처리를 수정하기 위해 우리 코드는 다음과 같이 될 것입니다.
def sum(nums): """ Try to catch all of our exceptions only. Re-raise them with more specific details. """ result = 0 try: iter(nums) except TypeError as e: raise TypeError("nums must be iterable") for n in nums: try: result += int(n) except TypeError as e: raise TypeError("stopped mid iteration since a non-integer was found") return result
이것이 어디로 가는지 알 수 있습니다. "적절하게" 확인하려고 하면 할수록 코드가 더 나빠집니다. 원본 코드와 비교하면 전혀 읽을 수 없습니다.
우리는 이것이 약간 극단적이라고 주장할 수 있습니다. 그러나 다른 한편으로 이것은 아주 단순한 예일 뿐입니다. 실제로 코드는 이보다 훨씬 더 복잡할 수 있습니다.
작은 예제를 "유형 검사 활성화"로 수정하려고 할 때 어떤 일이 발생하는지 보았습니다. 특정 유형을 강제하는 데 집중하는 대신 유형 힌트를 사용하면 유형을 사용자에게 명확하게 알릴 수 있습니다.
from typing import Iterable def sum(nums: Iterable[int]) -> int: result = 0 for n in nums: result += n return result
다음은 유형 힌트를 사용할 때의 몇 가지 이점입니다.
이제 코드가 실제로 좋아 보입니다!
유형 힌트를 사용하면 편집기에서 정적 유형 분석을 수행할 수 있습니다!
그것들은 함수/클래스에 저장되어 동적으로 사용할 수 있도록 합니다(예: typeguard
및 dataclasses
.
help(...)
를 사용할 때 함수에 표시됩니다.
설명을 기반으로 입력 유형이 올바른지 또는 더 나쁜 정보가 부족한지 온전한 확인을 할 필요가 없습니다.
"이 속성이 있습니까?" 와 같이 구조에 따라 힌트를 "입력"할 수 있습니다. 사용자가 하위 분류할 필요 없이
유형 힌트의 단점은 무엇입니까?
즉, 유형 검사를 제공하지 않기 때문에 실제로 질문에 대답하지 않습니다. 그럼에도 불구하고 유형 검사를 위해 여기에 있는 경우 유형 힌트도 제공 해야 합니다. 물론, 유형 검사가 실제로 필요하지 않다는 결론에 도달했지만 일종의 입력을 원할 경우 유형 힌트가 적합합니다.
유형을 확인하는 간단한 방법은 유형을 알고 있는 것과 비교하는 것입니다.
>>> a = 1 >>> type(a) == type(1) True >>> b = 'abc' >>> type(b) == type('') True
가장 좋은 방법은 변수를 잘 입력하는 것입니다. "입력" 라이브러리를 사용하여 이 작업을 수행할 수 있습니다.
예시:
from typing import NewType UserId = NewType ('UserId', int) some_id = UserId (524313`)
출처 : http:www.stackoverflow.com/questions/152580/whats-the-canonical-way-to-check-for-type-in-python
Android 애플리케이션에서 활동 간에 데이터를 어떻게 전달합니까? (0) | 2022.03.04 |
---|---|
객체 배열에서 속성 값을 배열로 추출 (0) | 2022.02.27 |
YAML에서 주석을 어떻게 차단합니까? (0) | 2022.02.27 |
전송 보안이 일반 텍스트 HTTP를 차단했습니다. (0) | 2022.02.27 |
개체 이름 앞에 단일 및 이중 밑줄의 의미는 무엇입니까? (0) | 2022.02.27 |