답변:
다른 (이미 좋은!) 답변의 내용을 요약하면 isinstance
상속을 제공하고 (파생 클래스 의 인스턴스도 기본 클래스 의 인스턴스입니다) 동일성을 검사 type
하지 않고 (유형의 ID를 요구하고 인스턴스를 거부합니다) 하위 유형, AKA 하위 클래스).
일반적으로 파이썬에서는 코드가 상속을 지원하기를 원합니다 (물론 상속이 너무 편리하기 때문에 코드를 사용하여 코드를 사용하는 것을 중지하는 것이 좋지 않습니다!). 그래서 완벽하게 지원하기 때문에 s의 isinstance
ID를 확인하는 것보다 나쁘지 않습니다. type
계승.
그것은하지 그입니다 isinstance
입니다 좋은 당신을 - 그것은 마음 그냥 덜 나쁜 종류의 평등을 확인하는 것보다. 인수를 사용해보십시오 : 정상, 파이썬, 선호하는 솔루션은 거의 예외없이 "오리 입력"입니다 것처럼 그것은에서 할, 그것은 특정 원하는 형식이었다 try
/ except
인수가 그 사실 아닌 경우 발생할 수있는 모든 예외를 잡는 문 유형 (또는 다른 유형은 멋지게 오리 모방 ;-)하고 except
절에서 다른 것을 시도하십시오 ( "아마"인 다른 유형의 인수를 사용하여).
basestring
있다 , 그러나, 존재하는 아주 특별한 경우-A 내장 타입 만이 사용하도록하려면 isinstance
(모두 str
와 unicode
서브 클래스 basestring
). 문자열은 시퀀스 (반복, 색인, 슬라이스 등) 일 수 있지만 일반적으로 문자열을 "스칼라"유형으로 취급하려고합니다. 모든 종류의 문자열을 처리하기에는 다소 불편합니다 (합리적으로 빈번한 사용 사례). 문자열 (그리고 아마도 다른 스칼라 타입, 즉 당신이 반복 할 수없는 타입), 다른 방법으로 모든 컨테이너 (목록, 세트, dicts ... ...)를 추가하고 basestring
플러스 isinstance
-전체 구조 관용구는 다음과 같습니다.
if isinstance(x, basestring)
return treatasscalar(x)
try:
return treatasiter(iter(x))
except TypeError:
return treatasscalar(x)
basestring
이를 추상 기본 클래스 ( "ABC") 라고 말할 수 있습니다. 서브 클래스에 구체적인 기능을 제공하지 않고 주로와 함께 사용하기위한 "마커"로 존재합니다 isinstance
. 파이썬에서 개념이 일반화되고있는 PEP 3119 가 채택되어 파이썬 2.6 및 3.0부터 구현 되었으므로이 개념은 분명히 파이썬에서 성장 하고 있습니다.
PEP는 ABC가 종종 오리 타이핑을 대신 할 수 있지만 일반적으로 그렇게해야한다는 큰 압력이 없음을 분명히합니다 ( 여기 참조 ). 그러나 최근 파이썬 버전에서 구현 된 ABC는 추가적인 장점을 제공합니다. isinstance
(그리고 issubclass
)는 이제 "[파생 클래스의 인스턴스" "이상의 의미를 가질 수 있습니다 (특히 모든 클래스는 ABC에"등록 "될 수 있음) 서브 클래스로 표시하고 해당 인스턴스를 ABC의 인스턴스로 표시). ABC는 또한 템플릿 메소드 디자인 패턴 응용 프로그램을 통해 매우 자연스러운 방식으로 실제 서브 클래스에 추가적인 편의성을 제공 할 수 있습니다 ( AB와 독립적으로 TM DP에 대한 자세한 내용은 여기 및 여기 [[파트 II] 참조). .
Python 2.6에서 제공되는 ABC 지원의 기본 메커니즘은 여기를 참조 하십시오 . 3.1 버전은 매우 유사하며 여기를 참조 하십시오 . 두 버전 모두 표준 라이브러리 모듈 모음 (3.1 버전) (매우 유사한 2.6 버전의 경우 여기 참조 )은 몇 가지 유용한 ABC를 제공합니다.
이 답변의 목적을 위해, 키 것은 (예 : 믹스 인 클래스의 고전 파이썬 대안에 비해 TM DP 기능에 대한 틀림없이 더 자연스럽게 배치, 넘어 상식에 대해 유지하는 UserDict.DictMixin ) 그들이 만드는 것입니다 isinstance
(과 issubclass
) 훨씬 더 매력적이고 널리 사용되는 (Python 2.6 이상) (2.5 이전 및 이전 버전), 이에 비해 최근의 Python 버전에서는 이전보다 이전에 유형 평등을 검사하는 것이 훨씬 더 나쁜 방법이되었습니다.
다음 은 불가능한 isinstance
것을 달성 하는 예입니다 type
.
class Vehicle:
pass
class Truck(Vehicle):
pass
이 경우 트럭 오브젝트는 Vehicle이지만 다음과 같은 결과를 얻습니다.
isinstance(Vehicle(), Vehicle) # returns True
type(Vehicle()) == Vehicle # returns True
isinstance(Truck(), Vehicle) # returns True
type(Truck()) == Vehicle # returns False, and this probably won't be what you want.
다시 말해, isinstance
서브 클래스에서도 마찬가지입니다.
파이썬에서 객체의 유형을 비교하는 방법을 참조하십시오.
type
더 이상 사용되지 않으며 isinstance
대신 사용 "하는 것으로 이해 됩니다. 예를 들어, 내가 원하는 것은 정확히 type()
확인하는 것이었지만 그 이유로 짧은 시간 동안 잘못 (그리고 약간 디버깅해야했습니다).
type()
하지 않은 경우에 부딪쳤다 isinstance()
. 하나는 좋지 않습니다. 그들은 다른 것들을위한 것입니다.
파이썬
isinstance()
과 차이점은type()
무엇입니까?
형식 검사
isinstance(obj, Base)
서브 클래스 및 여러 가능한 기본 인스턴스를 허용합니다.
isinstance(obj, (Base1, Base2))
반면에 형식 검사
type(obj) is Base
참조 된 유형 만 지원합니다.
(!) 참고로, is
보다 가능성이 더 적합
type(obj) == Base
클래스는 싱글 톤이기 때문입니다.
Python에서는 일반적으로 인수에 모든 유형을 허용하고 예상대로 처리하며 객체가 예상대로 작동하지 않으면 적절한 오류가 발생합니다. 이것은 다형성으로 알려져 있으며 오리 타이핑이라고도합니다.
def function_of_duck(duck):
duck.quack()
duck.swim()
위의 코드가 작동하면 논쟁은 오리라고 가정 할 수 있습니다. 따라서 오리의 실제 하위 유형 인 다른 것들을 전달할 수 있습니다.
function_of_duck(mallard)
또는 오리처럼 작동합니다.
function_of_duck(object_that_quacks_and_swims_like_a_duck)
우리 코드는 여전히 작동합니다.
그러나 명시 적으로 유형을 확인하는 것이 바람직한 경우가 있습니다. 아마도 다른 객체 유형과 관련이있는 현명한 일이있을 것입니다. 예를 들어 Pandas Dataframe 객체는 dicts 또는 레코드 . 이 경우 코드에서 올바르게 처리 할 수 있도록 인수 유형을 알아야합니다.
따라서 질문에 대답하려면 다음을 수행하십시오.
isinstance()
과 차이점은 type()
무엇입니까?차이점을 보여줄 수 있습니다.
type
함수가 특정 종류의 인수 (생성자의 일반적인 사용 사례)를 얻는 경우 특정 동작을 보장해야한다고 가정하십시오. 다음과 같은 유형을 확인하면
def foo(data):
'''accepts a dict to construct something, string support in future'''
if type(data) is not dict:
# we're only going to test for dicts for now
raise ValueError('only dicts are supported for now')
dict
(우리가 코드가 Liskov Substitution 의 원칙을 따를 것으로 기대한다면 , 서브 타입이 타입으로 대체 될 수 있음) 서브 클래스 인 dict을 전달하려고 하면 코드가 깨집니다! :
from collections import OrderedDict
foo(OrderedDict([('foo', 'bar'), ('fizz', 'buzz')]))
오류가 발생합니다!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in foo
ValueError: argument must be a dict
isinstance
그러나를 사용하면 isinstance
Liskov 대체를 지원할 수 있습니다! :
def foo(a_dict):
if not isinstance(a_dict, dict):
raise ValueError('argument must be a dict')
return a_dict
foo(OrderedDict([('foo', 'bar'), ('fizz', 'buzz')]))
보고 OrderedDict([('foo', 'bar'), ('fizz', 'buzz')])
사실, 우리는 더 잘할 수 있습니다. collections
다양한 유형에 최소 프로토콜을 적용하는 추상 기본 클래스를 제공합니다. 이 경우 Mapping
프로토콜 만 기대 하면 다음을 수행 할 수 있으며 코드가 훨씬 유연 해집니다.
from collections import Mapping
def foo(a_dict):
if not isinstance(a_dict, Mapping):
raise ValueError('argument must be a dict')
return a_dict
유형을 사용하여 여러 클래스를 확인하는 데 사용할 수 있습니다.
type(obj) in (A, B, C)
예, 유형이 동일한 지 테스트 할 수 있지만 위 유형 대신 제어 유형에 여러 기준을 사용하십시오 (단, 해당 유형 만 허용하지 않는 한).
isinstance(obj, (A, B, C))
차이점 isinstance
은 Liskov 대체로 알려진 속성 인 프로그램을 중단하지 않고 부모를 대신 할 수있는 서브 클래스 를 지원한다는 것입니다.
그러나 종속성을 반전시키고 특정 유형을 전혀 확인하지 않는 것이 좋습니다.
따라서 우리는 대체 서브 클래스를 지원하기를 원하기 때문에 인스턴스의 정확한 클래스를 알 필요가 없다면 type
타입 검사를 피하고 타입 검사를 선호 isinstance
합니다.
isinstance(instance, y)
하고 사용하는 곳에 from v.w.x import y
해당 검사를 가져 오지만 인스턴스 instance
를 생성 할 때 from x import y
your_module.py에서 y를 가져 오는 방법 대신 사용 하면 isinstance 검사는 동일한 클래스 임에도 불구하고 실패합니다.
파이썬 문서에 따르면 여기에 진술이 있습니다.
8.15. 유형 — 내장 유형의 이름
Python 2.2부터는 내장 팩토리 함수 (예 :
int()
및str()
해당 유형의 이름)가 있습니다.
따라서 isinstance()
보다 선호해야합니다 type()
.
실제 차이점에 대해서는에서 찾을 수 code
있지만의 기본 동작 구현을 찾을 수 없습니다 isinstance()
.
그러나 __instancecheck__ 에 따라 비슷한 abc .__ instancecheck__을 얻을 수 있습니다 .
위 abc.__instancecheck__
, 아래 테스트를 사용 후 :
# file tree
# /test/__init__.py
# /test/aaa/__init__.py
# /test/aaa/aa.py
class b():
pass
# /test/aaa/a.py
import sys
sys.path.append('/test')
from aaa.aa import b
from aa import b as c
d = b()
print(b, c, d.__class__)
for i in [b, c, object]:
print(i, '__subclasses__', i.__subclasses__())
print(i, '__mro__', i.__mro__)
print(i, '__subclasshook__', i.__subclasshook__(d.__class__))
print(i, '__subclasshook__', i.__subclasshook__(type(d)))
print(isinstance(d, b))
print(isinstance(d, c))
<class 'aaa.aa.b'> <class 'aa.b'> <class 'aaa.aa.b'>
<class 'aaa.aa.b'> __subclasses__ []
<class 'aaa.aa.b'> __mro__ (<class 'aaa.aa.b'>, <class 'object'>)
<class 'aaa.aa.b'> __subclasshook__ NotImplemented
<class 'aaa.aa.b'> __subclasshook__ NotImplemented
<class 'aa.b'> __subclasses__ []
<class 'aa.b'> __mro__ (<class 'aa.b'>, <class 'object'>)
<class 'aa.b'> __subclasshook__ NotImplemented
<class 'aa.b'> __subclasshook__ NotImplemented
<class 'object'> __subclasses__ [..., <class 'aaa.aa.b'>, <class 'aa.b'>]
<class 'object'> __mro__ (<class 'object'>,)
<class 'object'> __subclasshook__ NotImplemented
<class 'object'> __subclasshook__ NotImplemented
True
False
나는이 결론을 얻는다 type
.
# according to `abc.__instancecheck__`, they are maybe different! I have not found negative one
type(INSTANCE) ~= INSTANCE.__class__
type(CLASS) ~= CLASS.__class__
의 경우 isinstance
:
# guess from `abc.__instancecheck__`
return any(c in cls.__mro__ or c in cls.__subclasses__ or cls.__subclasshook__(c) for c in {INSTANCE.__class__, type(INSTANCE)})
BTW :보다 효율적으로 사용하는 혼합하지 않기 위하여 relative and absolutely import
, 사용 absolutely import
project_dir에서을 (추가 sys.path
)
str
와unicode
(그냥 확인할 수있는 곳basestring
), 여러 유형에 대해 확인하기 위해 튜플을 사용할 수 있습니다. 있는지 확인하려면something
ISint
또는str
사용isinstance(something, (int, str))
.