주어진 객체가 주어진 유형인지 확인하는 가장 좋은 방법은 무엇입니까? 주어진 유형에서 객체가 상속되는지 확인하는 것은 어떻습니까?
객체가 있다고 가정 해 봅시다 o
. 그것이 아닌지 어떻게 확인 str
합니까?
주어진 객체가 주어진 유형인지 확인하는 가장 좋은 방법은 무엇입니까? 주어진 유형에서 객체가 상속되는지 확인하는 것은 어떻습니까?
객체가 있다고 가정 해 봅시다 o
. 그것이 아닌지 어떻게 확인 str
합니까?
답변:
o
의 인스턴스 str
또는 하위 클래스인지 확인하려면 isinstance를str
사용 하십시오 ( "정식"방식 임).
if isinstance(o, str):
유형 o
이 정확한지 확인하려면 str
(하위 클래스 제외) :
if type(o) is str:
다음도 작동하며 경우에 따라 유용 할 수 있습니다.
if issubclass(type(o), str):
참조 - 내장의 기능을 관련 정보는 파이썬 라이브러리 참조에.
한 가지 더 참고 :이 경우 Python 2를 사용하는 경우 실제로 다음을 사용할 수 있습니다.
if isinstance(o, basestring):
이것은 또한 유니 코드 문자열을 잡을 것입니다 (때문에 unicode
의 서브 클래스가 아닌 str
, 모두 str
와 unicode
의 서브 클래스 basestring
). 참고 basestring
더 이상 거기에 파이썬 3에 존재하는 엄격한 분리 문자열 ( str
)와 바이너리 데이터 ( bytes
).
또는 isinstance
튜플 클래스를 허용합니다. 다음 중 하나의 하위 클래스의 인스턴스 인 True
경우 이를 반환 합니다 .o
(str, unicode)
if isinstance(o, (str, unicode)):
type(a) is Object
사실이 아닙니다 isinstance(a, Object)
. 그러나, type(a) is SubClassOfObject
다음 type(a) is Object == False
,하지만 isinstance(a, Object) == True
. 권리?
a is b
a와 b가 정확히 같은 것을 의미합니다. 즉, 메모리의 동일한 엔티티에 대한 참조입니다. 그래서 a
그리고 b
에서와 같이 동일한 클래스가 아닌 서브 클래스가 될 것이다 isinstance()
. 예를 들어 stackoverflow.com/a/133024/1072212
대부분의 객체의 유형을 확인하는 파이썬 방법은 그것을 확인하지 ...입니다.
파이썬은 장려 때문에 오리 타이핑을 , 당신은해야 try...except
개체의 방법 당신이 그들을 사용하려는 방법을 사용합니다. 따라서 함수가 쓰기 가능한 파일 객체를 찾고 있다면 이 클래스의 하위 클래스인지 확인 하지 말고 메소드 file
를 사용하십시오 .write()
!
물론,이 멋진 추상화는 때때로 분해되어 isinstance(obj, cls)
필요한 것입니다. 그러나 드물게 사용하십시오.
if hasattr(ob, "write") and callable(ob.write):
... 또는 일부 DICT 액세스를 저장func = getattr(ob, "write", None)
if callable(func): ...
hasattr
만 억제 합니다-참조 : docs.python.org/3.4/library/functions.html#hasattr
isinstance(o, str)
반환 할 True
경우 o
인 str
또는 상속에서 유형이다 str
.
type(o) is str
str 인 True
경우에만 반환 됩니다 o
. 에서 상속되는 유형 인 False
경우 반환 됩니다 .o
str
isinstance
과는 type(var) == type('')
분명하지 않다.
질문을하고 대답 한 후에, 타입 힌트가 파이썬에 추가되었습니다 . 파이썬에서 타입 힌트는 타입을 검사 할 수 있지만 정적으로 타입이 지정된 언어와는 매우 다른 방식으로 검사됩니다. 파이썬에서 유형 힌트 기능과 관련된 런타임 액세스 할 수있는 데이터 등의 기능을 인수의 예상 유형을 연결하고이 허용 유형을 확인하는. 유형 힌트 구문의 예 :
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과 함께 제공되는 것은 아니지만 일부 "공식"수준 인 것 같습니다.
이 방법으로 형식 검사는 정적으로 형식화 된 컴파일 된 언어의 형식 검사와 다릅니다. 파이썬에서 타입은 동적이기 때문에 타입 검사는 런타임에 이루어져야합니다. 우리는 모든 프로그램이 필요할 때마다 올바른 프로그램에서도 비용을 부과합니다. 명시 적 유형 검사는 필요 이상으로 제한적일 수 있으며 불필요한 오류를 유발할 수 있습니다 (예 : 인수가 실제로 정확히 list
유형 이어야 하거나 반복 가능한 것입니까?).
명시 적 유형 검사의 단점은 더 일찍 오류를 포착하고 덕 타이핑보다 명확한 오류 메시지를 표시 할 수 있다는 것입니다. 오리 유형의 정확한 요구 사항은 외부 문서로만 표현할 수 있으며 (완전하고 정확해야 함) 호환되지 않는 유형의 오류는 원래 위치와는 거리가 멀어 질 수 있습니다.
파이썬의 타입 힌트는 타입을 지정하고 확인할 수 있지만 일반적인 코드 실행 중에 추가 비용이 들지 않는 절충안을 제공하기위한 것입니다.
typing
타입 힌트에서 사용할 수있는 패키지 이벤트 유형 변수는 특정 유형을 필요로하지 않고 필요한 행동을 표현한다. 예를 들어, 이러한 동작과 함께 모든 유형의 필요성을 지정하는 힌트 Iterable
와 같은 변수가 포함됩니다 Callable
.
타입 힌트는 타입을 확인하는 가장 파이썬적인 방법이지만, 타입을 전혀 확인하지 않고 오리 타이핑에 의존하는 것이 더 파이썬적인 경우가 많습니다. 유형 힌트는 비교적 새롭고 배심원은 가장 파이썬적인 솔루션 일 때 여전히 사용 중입니다. 비교적 논쟁의 여지가 없지만 매우 일반적인 비교 : 유형 힌트는 시행 할 수있는 문서 형식을 제공하며, 코드를 조기에 생성하고 오류를 이해하기 쉽게 만들 수 있으며, 오리 입력으로 할 수없는 오류를 포착 할 수 있으며, 비정상적으로 정적 인 검사가 가능합니다 감각이지만 여전히 런타임 외부에 있습니다.) 다른 한편으로, 오리 타이핑은 오랫동안 파이썬 방식이었으며 정적 타이핑의인지 오버 헤드를 부과하지 않으며 덜 장황하며 모든 실행 가능한 유형과 일부를 허용합니다.
mypy
사용하는 파이썬 모듈입니다 importlib
. 이것이 "정적 유형 검사"인지 여부는 철학적 인 질문이지만 일반 언어 통역사와 수입 기계가 관련되어 있기 때문에 가장 기대되는 것과 다릅니다.
언제 오리 타이핑이 위험한지 알지 못하고 악한 이유는 다음과 같습니다. 예를 들면 다음과 같습니다. 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()
class EvilDuck(Duck)
talk ()를 만들고 재정의 할 수 있습니다 . 또는 class ChineseCancerDuck(Duck)
몇 년이 지나도 나타나지 않는 심한 부작용이있을 수 있습니다. 당신 : 당신의 아이를 감독 (철저하게 그녀의 장난감을 테스트 더 나을 것
__file__
일반적으로 파일과 같은 객체를 식별하는 데 사용되는 속성 을 재정 의하여 다른 것을 의미 함으로써 많은 Python 코드를 사용할 수 있습니다.
isinstance(o, str)
파이썬과 같은 동적 언어를 사용하는 것에 대한 멋진 점은 실제로 그런 것을 확인할 필요가 없다는 것입니다.
객체에서 필요한 메소드를 호출하고을 잡을 것 AttributeError
입니다. 나중에 이것으로 다른 (아마 관련이없는) 객체로 메소드를 호출하여 테스트를 위해 객체를 조롱하는 것과 같은 다른 작업을 수행 할 수 있습니다.
객체 와 같은 파일urllib2.urlopen()
을 반환하는 웹에서 데이터를 가져올 때 이것을 많이 사용했습니다 . 이것은 실제 파일 과 동일한 방법을 구현하기 때문에 파일에서 읽는 거의 모든 방법으로 전달 될 수 있습니다 .read()
그러나을 사용할 시간과 장소가 있다고 확신합니다 isinstance()
. 그렇지 않으면 아마도 없을 것입니다 :)
더 복잡한 유형 유효성 검사를 위해 파이썬 유형 힌트 주석을 기반으로 유효성을 검사하는 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)
유형의 __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'
휴고 :
아마도 list
오히려 의미 가 array
아니지만 유형 검사의 모든 문제를 지적합니다. 문제의 객체가 목록인지 여부를 알고 싶지 않으며, 어떤 종류의 시퀀스인지 또는 단일 객체인지 알고 싶습니다. 시퀀스처럼 사용하십시오.
기존 시퀀스에 객체를 추가하거나 객체 시퀀스 인 경우 모두 추가
try:
my_sequence.extend(o)
except TypeError:
my_sequence.append(o)
문자열 및 / 또는 문자열 시퀀스로 작업하는 경우 한 가지 트릭이 있습니다. 문자열은 종종 단일 객체로 생각되기 때문에 까다 롭지 만 문자 시퀀스이기도합니다. 그보다 더 나쁜 것은 실제로 단일 길이 문자열의 시퀀스이기 때문입니다.
일반적으로 API는 단일 값 또는 시퀀스 만 허용하도록 API를 설계하도록 선택합니다. [ ]
필요한 경우 단일 값을 전달할 때 어렵지 않습니다 .
(이것은 문자열처럼 보이기 때문에 문자열에 오류가 발생할 수 있습니다.)
가장 좋은 방법은 변수를 잘 입력하는 것입니다. "타이핑"라이브러리를 사용하면됩니다.
예:
from typing import NewType
UserId = NewType ('UserId', int)
some_id = UserId (524313
)`