Python에서 유형을 확인하는 표준 방법은 무엇입니까?
개체가 지정된 유형인지 또는 지정된 유형에서 상속되는지 확인하려면 어떻게 해야 합니까?
오브젝트 확인 방법o
종류str
?
이 명령어를 사용하여o
의 예다.str
또는 의 서브클래스str
:
if isinstance(o, str):
타입이 다음 중 하나인지 확인하려면o
바로 그렇다str
의 서브클래스는 제외합니다.
if type(o) is str:
위의 또 다른 대안:
if issubclass(type(o), str):
관련 정보는 Python Library Reference의 내장 함수를 참조하십시오.
Python 2에서 문자열 확인 중
Python 2의 경우, 이것은 다음 중 하나를 확인하는 더 좋은 방법입니다.o
는 문자열입니다.
if isinstance(o, basestring):
유니코드 문자열도 잡히니까요.unicode
의 서브클래스가 아닙니다.str
; 반면, 둘 다str
그리고.unicode
의 서브클래스입니다.Python 3에서는basestring
문자열()str
과 바이너리 데이터()bytes
를 엄격하게 분리하기 때문에 더 이상 존재하지 않습니다.
또,isinstance
는 일련의 클래스를 받아들입니다.이것은 돌아올 것이다.True
한다면o
다음 중 하나의 서브클래스의 인스턴스입니다.(str, unicode)
:
if isinstance(o, (str, unicode)):
물체의 종류를 확인하는 가장 큰 방법은...체크하지 마세요.
Python은 Duck Typing을 권장하기 때문에, 당신은 그냥 Duck Typing을 추천try...except
오브젝트의 메서드를 원하는 방식으로 사용할 수 있습니다.따라서 함수가 쓰기 가능한 파일 개체를 찾고 있는 경우 해당 개체가 다음 하위 클래스인지 확인하지 마십시오.file
를 사용해 보세요..write()
메서드!
물론 가끔은 이런 멋진 추상화들이 무너지기도 하고isinstance(obj, cls)
그게 네게 필요한 거야하지만 적게 사용하세요.
isinstance(o, str)
돌아온다True
한다면o
는 입니다.str
또는 에서 상속되는 타입입니다.str
.
type(o) is str
돌아온다True
만약이라면o
str입니다.그것은 돌아올 것이다.False
한다면o
에서 상속되는 타입입니다.str
.
질문 및 답변 후 유형 힌트가 Python에 추가되었습니다.Python의 type hints는 정적 입력 언어와는 매우 다른 방법으로 유형을 확인할 수 있습니다.Python에서 type hints는 예상되는 인수 유형을 함수와 관련된 런타임 액세스 가능한 데이터로 함수와 관련지어 유형을 확인할 수 있도록 합니다.type hint 구문의 예:
def foo(i: int):
return i
foo(5)
foo('oops')
이 경우, 에러가 트리거 됩니다.foo('oops')
주석에 의한 인수의 유형은int
. 타입 힌트가 추가되어도 스크립트가 정상적으로 실행되어도 에러는 발생하지 않습니다.그러나 다른 프로그램이 쿼리하여 유형 오류를 확인하는 데 사용할 수 있는 예상 유형을 설명하는 함수에 속성을 추가합니다.
유형 오류를 찾기 위해 사용할 수 있는 다른 프로그램 중 하나는 다음과 같습니다.mypy
:
mypy script.py
script.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "int"
(설치가 필요할 수 있습니다.mypy
패키지 매니저에게 문의해 주십시오.CPython에는 포함되어 있지 않다고 생각합니다만, 어느 정도의 「공식」이 있는 것 같습니다).
이 방법에서의 Type Checking은 정적으로 입력된 컴파일 언어에서의 Type Check와는 다릅니다.Python에서는 타입이 동적이기 때문에 타입 체크는 런타임에 실행되어야 합니다.따라서 매번 발생한다고 주장하면 올바른 프로그램이라도 비용이 듭니다.명시적 유형 검사는 또한 필요 이상으로 제한적일 수 있으며 불필요한 오류를 유발할 수 있습니다(예: 인수가 정말로 정확하게 필요합니까?list
또는 반복할 수 있는 것으로 충분합니까?)
명시적 유형 확인의 장점은 오류를 더 빨리 포착할 수 있고 덕 타이핑보다 더 명확한 오류 메시지를 제공할 수 있다는 것입니다.duck 타입의 정확한 요건은 외부 문서(완전하고 정확한 것을 희망함)를 통해서만 표현할 수 있으며, 호환되지 않는 타입의 오류는 발생원으로부터 멀리 떨어진 곳에서 발생할 수 있습니다.
Python의 타입 힌트는 타입을 지정하고 체크할 수 있지만 통상적인 코드 실행 중에 추가 비용이 발생하지 않는 타협점을 제공하기 위한 것입니다.
그typing
패키지는 특정 유형을 요구하지 않고 필요한 동작을 표현하기 위해 유형 힌트에서 사용할 수 있는 유형 변수를 제공합니다.예를 들어 다음과 같은 변수가 포함됩니다.Iterable
그리고.Callable
이러한 동작에 대한 모든 유형의 필요성을 지정하는 힌트입니다.
활자 힌트가 활자를 확인하는 가장 큰 방법인 반면, 활자를 전혀 확인하지 않고 오리 타자에 의존하는 것이 종종 더 피톤적이다.유형 힌트는 비교적 새로운 것이고 배심원들은 언제가 가장 피톤적인 해결책인지에 대해 아직 결정을 내리지 못했다.비교적 논란의 여지가 없지만 매우 일반적인 비교:유형 힌트는 적용 가능한 문서 형식을 제공하며, 코드가 더 빠르고 이해하기 쉬운 오류를 생성하도록 허용하고, 덕 타이핑이 불가능한 오류를 포착할 수 있으며, 정적 검사(비정상적인 의미이지만 여전히 런타임 외)를 수행할 수 있습니다.반면에, 오리타자는 오랫동안 피톤식 방식이었고, 정적 타이핑의 인지적 오버헤드를 강요하지 않고, 덜 장황하고, 모든 실행 가능한 타입과 그 중 일부를 받아들인다.
>>> isinstance('1223', int | str)
True
>>> isinstance('abcd', int | str)
True
변수의 유형은 __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'
여기 왜 오리타자가 위험한지 모르는 것이 나쁜지에 대한 예가 있다.
예:여기 Python 코드가 있습니다(적절한 들여쓰기를 생략할 수 있음). 이 상황은 duck이 정말 필요할 때 폭탄이 발생하지 않도록 isinstance와 issubclassof 함수를 관리함으로써 피할 수 있습니다.
class Bomb:
def talk(self):
self.explode()
def explode(self):
print("BOOM!, The bomb explodes.")
class Duck:
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 take_duck(self, duck):
self.kids_duck = duck
print("The kid accepts the duck, and happily skips along.")
def do_your_thing(self):
print("The kid tries to get the duck to talk.")
self.kids_duck.talk()
my_kid = Kid()
my_kid.take_duck(Bomb())
my_kid.do_your_thing()
주의: 예시는 오래되고 순진하며 위험은 크게 과장되어 있습니다.Python 3로의 업데이트 이외에는 큰 편집 없이 개념 증명으로 남습니다.나는 왜 내가 원래 이것을 쓰도록 강요했는지 기억나지 않는다.
isinstance(o, str)
좀 더 복잡한 타입 검증의 경우 파이썬 타입 힌트 주석을 기반으로 검증하는 타입가드의 접근방식이 마음에 듭니다.
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과 같은 역동적인 언어를 사용하는 것의 멋진 점은 그런 것을 확인할 필요가 없다는 것입니다.
전 그냥 당신의 오브젝트에 필요한 메서드를 호출해서AttributeError
나중에 테스트 대상 오브젝트를 조롱하는 등의 다양한 작업을 수행하기 위해 다른 (관련성이 없는 것처럼 보이는) 오브젝트를 사용하여 메서드를 호출할 수 있습니다.
웹에서 데이터를 가져올 때 많이 사용하고 있습니다.urllib2.urlopen()
오브젝트와 같은 파일을 반환합니다.이것은, 파일로부터 읽어내는 거의 모든 방법으로 전달할 수 있습니다.이것은, 같은 기능을 실장하기 때문입니다.read()
메서드를 실제 파일로 만듭니다.
하지만 이 제품을 사용할 시간과 장소는 있을 거예요.isinstance()
그렇지 않으면 아마 존재하지 않을 것입니다. : )
승인된 답변은 질문에 대한 답변을 제공한다는 점에서 질문에 대한 답변입니다.
Q: 특정 객체가 특정 유형인지 확인하는 가장 좋은 방법은 무엇입니까?개체가 지정된 유형에서 상속되는지 확인하는 것은 어떻습니까?
A: 사용
isinstance, issubclass, type
타입에 따라 체크합니다.
그러나 다른 답변과 코멘트가 빠르게 지적되듯이, "타입 체크"라는 발상은 비단뱀보다 훨씬 더 많은 것이 있다.Python 3와 type hints가 추가된 이후, 많은 것도 바뀌었습니다.아래에서는 활자 검사, 오리 타이핑, 예외 처리의 어려움을 몇 가지 살펴봅니다.타입 체크가 필요없다고 생각되는 분(통상 필요없지만, 여기 있습니다)을 위해서, 타입 힌트를 사용하는 방법도 지적합니다.
유형 확인
python에서는 타입 체크가 항상 적절한 것은 아닙니다.다음 예를 생각해 보겠습니다.
def sum(nums):
"""Expect an iterable of integers and return the sum."""
result = 0
for n in nums:
result += n
return result
입력이 정수로 반복 가능한지 확인하기 위해 중요한 문제에 부딪힙니다.모든 요소가 정수인지 확인하는 유일한 방법은 루프 스루를 통해 각 요소를 확인하는 것입니다.하지만 반복기 전체를 통과하면 의도된 코드에는 아무것도 남지 않습니다.이런 상황에서는 두 가지 선택지가 있습니다.
루프할 때 확인해.
미리 확인하시고 확인하신 대로 보관하세요.
옵션 1은 코드를 복잡하게 만드는 단점이 있으며, 특히 많은 장소에서 유사한 검사를 수행해야 하는 경우에는 더욱 그렇습니다.이 때문에 타입 체크를 함수의 상단에서 코드에서 반복 가능한 것을 사용하는 모든 곳으로 이동시킬 수 있습니다.
옵션 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
).
그러나 예외 처리를 좋게 만드는 정확한 이유 또한 그들의 몰락일 수 있습니다.
A
float
isn't anint
, but it satisfies the behavioral requirements to work.It is also bad practice to wrap the entire code with a try-except block.
At first these may not seem like issues, but here's some reasons that may change your mind.
A user can no longer expect our function to return an
int
as intended. This may break code elsewhere.Since exceptions can come from a wide variety of sources, using the try-except on the whole code block may end up catching exceptions you didn't intend to. We only wanted to check if
nums
was iterable and had integer elements.Ideally we'd like to catch exceptions our code generators and raise, in their place, more informative exceptions. It's not fun when an exception is raised from someone else's code with no explanation other than a line you didn't write and that some
TypeError
occured.
In order to fix the exception handling in response to the above points, our code would then become this... abomination.
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
You can kinda see where this is going. The more we try to "properly" check things, the worse our code is looking. Compared to the original code, this isn't readable at all.
We could argue perhaps this is a bit extreme. But on the other hand, this is only a very simple example. In practice, your code is probably much more complicated than this.
Type Hints
We've seen what happens when we try to modify our small example to "enable type checking". Rather than focusing on trying to force specific types, type hinting allows for a way to make types clear to users.
from typing import Iterable
def sum(nums: Iterable[int]) -> int:
result = 0
for n in nums:
result += n
return result
Here are some advantages to using type-hints.
The code actually looks good now!
Static type analysis may be performed by your editor if you use type hints!
They are stored on the function/class, making them dynamically usable e.g.
typeguard
anddataclasses
.They show up for functions when using
help(...)
.No need to sanity check if your input type is right based on a description or worse lack thereof.
You can "type" hint based on structure e.g. "does it have this attribute?" without requiring subclassing by the user.
The downside to type hinting?
- 유형 힌트 자체는 구문과 특수 텍스트에 지나지 않습니다.타입 체크와는 다릅니다.
즉, 유형 확인을 제공하지 않기 때문에 실제로 질문에 답하지 않습니다.단, 타입 체크가 필요한 경우에는 타입 힌트도 필요합니다.물론, 실제로 활자 검사가 필요하지 않다고 결론을 내렸다면, 활자 힌트를 입력해 주세요.
Hugo 앞으로:
아마 그 말은list
보다는array
그러나 이는 유형 확인의 전체 문제를 나타냅니다. 문제의 객체가 목록인지 아닌지를 알고 싶은 것이 아니라 시퀀스인지 단일 객체인지 알고 싶은 것입니다.그러니까 이걸 순서처럼 쓰도록 해.
개체를 기존 시퀀스에 추가하거나 개체의 시퀀스인 경우 모두 추가합니다.
try:
my_sequence.extend(o)
except TypeError:
my_sequence.append(o)
하나의 트릭은 문자열 및/또는 문자열 시퀀스로 작업하는 경우입니다.흔히 문자열은 하나의 오브젝트로 생각되지만 문자 시퀀스이기도 합니다.그것보다 더 안 좋은 것은, 실제로는 단일 길이의 문자열의 연속이기 때문입니다.
저는 보통 API를 하나의 값 또는 시퀀스를 받아들이도록 설계합니다.그러면 일이 쉬워집니다.를 넣는 것은 어렵지 않다.[ ]
필요한 경우 전달할 때 단일 값을 기준으로 합니다.
(문자열에서는 에러가 발생할 수 있습니다만, 시퀀스처럼 보입니다).
유형을 확인하는 간단한 방법은 자신이 알고 있는 유형과 비교하는 것입니다.
>>> 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`)
https://docs.python.org/3/library/typing.html 를 참조해 주세요.
언급URL : https://stackoverflow.com/questions/152580/whats-the-canonical-way-to-check-for-type-in-python
'source' 카테고리의 다른 글
속도 템플릿과 유사한 Java 문자열 치환 (0) | 2022.11.08 |
---|---|
VueJS 자동화 - 테스트 카페와나이트워치 - 장점 / 단점 (0) | 2022.11.08 |
사용자 정의 예외 유형 (0) | 2022.11.08 |
자바에는 eval() 함수가 있나요? (0) | 2022.11.08 |
Java reflection을 사용하여 메서드 파라미터명을 얻을 수 있습니까? (0) | 2022.11.08 |