파이썬에서 유형을 확인하는 정식 방법은 무엇입니까?


1277

주어진 객체가 주어진 유형인지 확인하는 가장 좋은 방법은 무엇입니까? 주어진 유형에서 객체가 상속되는지 확인하는 것은 어떻습니까?

객체가 있다고 가정 해 봅시다 o. 그것이 아닌지 어떻게 확인 str합니까?


7
글쎄, 파이썬에서 정식 접근 방식은 유형을 전혀 확인하지 않는 것입니다 (디버깅하지 않는 한). 일반적으로 문자열로 사용하려고합니다 (예 : 다른 문자열과 연결, 콘솔로 인쇄 등). 실패한다고 생각되면 try / except 또는 hasattr을 사용하십시오. 즉, 받아 들여진 대답은 파이썬 세계에서 일반적으로 "하지 말아야 할"일을 수행하는 정식 방법입니다. 더 많은 정보는 "파이썬 오리 입력을"구글이나 다음을 읽어 voidspace.org.uk/python/articles/duck_typing.shtml stackoverflow.com/questions/610883/...을
존 쿰즈에게

9
Coombs는 JSON이 아닌 직렬화 가능 클래스와 같은 예제를 간과하고 있다고 생각합니다. 큰 데이터 청크를 함수 (코드에 영향을 줄 수없는)를 통해 넣는 경우 전달하기 전에 해당 데이터의 특정 부분을 <str>으로 변환하려고 할 수 있습니다. 적어도 그 방법은 내가 ...이 페이지에 종료
존 Carrell

2
이것을 요구하는 가장 일반적인 이유는 문자열과 반복 가능한 문자열을 구별하기를 원하기 때문입니다. 문자열 반복 가능한 문자열이기 때문에 까다로운 질문입니다 . 단일 문자 문자열은 심지어 자체 시퀀스입니다 (마지막으로 확인한 시간은 의존하지 않아야 함). 그러나 누군가 문자열 같은 것을 사용했을 것입니까? . 따라서 "문자열과 다른 반복 가능한 문자열을 구별하려면 어떻게해야합니까?" "당신이하려는 일에 달려 있습니다." :-D
clacke

2
파이썬 타입 주석은 이제 일입니다. mypy
Sheena

답변:


1522

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, 모두 strunicode의 서브 클래스 basestring). 참고 basestring더 이상 거기에 파이썬 3에 존재하는 엄격한 분리 문자열 ( str)와 바이너리 데이터 ( bytes).

또는 isinstance튜플 클래스를 허용합니다. 다음 중 하나의 하위 클래스의 인스턴스 인 True경우 이를 반환 합니다 .o(str, unicode)

if isinstance(o, (str, unicode)):

31
str .__ subclasses __ ()는 str의 직접 서브 클래스 만 리턴하며 issubclass () 또는 isinstance ()와 동일한 기능을 수행하지 않습니다. (그렇게하려면) (__ 재귀 적으로 호출 .__ 서브 클래스에있을 것입니다.
토마스 Wouters

15
이것은 좋은 대답이지만, 실제로 파이썬에서 이것을해서는 안된다는 경고로 시작해야한다고 생각합니다. 그대로, 이것이 "파이썬에서 할 수있는 정식적인 일"이라는 가정을 검증하는 것 같습니다.
Jon Coombs

4
이것들은 python2 답변입니다. 예를 들어 python3에는 기본 문자열이 없습니다.
dfrankow

4
인스턴스와 "정확하게"의 차이점은 무엇입니까? 그렇다면 type(a) is Object사실이 아닙니다 isinstance(a, Object). 그러나, type(a) is SubClassOfObject다음 type(a) is Object == False,하지만 isinstance(a, Object) == True. 권리?
mavavilj

1
@mavavilj- a is ba와 b가 정확히 같은 것을 의미합니다. 즉, 메모리의 동일한 엔티티에 대한 참조입니다. 그래서 a그리고 b에서와 같이 동일한 클래스가 아닌 서브 클래스가 될 것이다 isinstance(). 예를 들어 stackoverflow.com/a/133024/1072212
Terry Brown

196

대부분의 객체의 유형을 확인하는 파이썬 방법은 그것을 확인하지 ...입니다.

파이썬은 장려 때문에 오리 타이핑을 , 당신은해야 try...except개체의 방법 당신이 그들을 사용하려는 방법을 사용합니다. 따라서 함수가 쓰기 가능한 파일 객체를 찾고 있다면 이 클래스의 하위 클래스인지 확인 하지 말고 메소드 file를 사용하십시오 .write()!

물론,이 멋진 추상화는 때때로 분해되어 isinstance(obj, cls)필요한 것입니다. 그러나 드물게 사용하십시오.


75
IMHO, 가장 파이썬적인 방법은 주어진 인수에 대처하는 것입니다. 내 코드에서는 종종 객체 또는 객체 배열을 수신하는지 알 수 없으며 내부에서 유형 검사를 사용하여 단일 객체를 단일 요소 목록으로 변환합니다.
sastanin

14
대신 쓰기 메소드를 사용하려고하면 예외 없이이 작업을 수행하려고 할 때가 있습니다. 이 경우 당신이 할 ... 수 if hasattr(ob, "write") and callable(ob.write): ... 또는 일부 DICT 액세스를 저장func = getattr(ob, "write", None) if callable(func): ...
ideasman42

142
오리 타이핑은 라이브러리 사용에 관한 것입니다. 유형 검사는 라이브러리 작성 에 관한 입니다. 동일한 문제 도메인이 아닙니다.
RickyA

16
@RickyA, 나는 동의하지 않습니다. 오리 타이핑은 잘 알려진 의미론을 가진 인터페이스를 사용하여 객체와 상호 작용하는 것입니다. 이것은 라이브러리 코드 또는 이러한 라이브러리를 사용하는 코드에 적용 할 수 있습니다.
Dan Lenski

6
@ nyuszika7h, Python3에서는 AttributeError hasattr만 억제 합니다-참조 : docs.python.org/3.4/library/functions.html#hasattr
ideasman42

57

isinstance(o, str)반환 할 True경우 ostr또는 상속에서 유형이다 str.

type(o) is strstr 인 True경우에만 반환 됩니다 o. 에서 상속되는 유형 인 False경우 반환 됩니다 .ostr


6
물론 객체가 'str'의 인스턴스가 아니라 대신 문자열과 비슷한 인스턴스 인 경우에는 실패합니다. 유니 코드, mmap, UserString 또는 기타 사용자 정의 유형과 같습니다. 파이썬에서 일반적인 접근 방식은 유형 검사를 수행하지 않는 것입니다.
Thomas Wouters

6
사과 할 필요는 없습니다. 자신의 질문에 대답해도됩니다. 카르마가 아닌 대답에 대한 것입니다.
Eli Bendersky

2
이것은 매우 도움이됩니다. 의 차이 때문에 isinstance과는 type(var) == type('')분명하지 않다.
sastanin

30

질문을하고 대답 한 후에, 타입 힌트가 파이썬에 추가되었습니다 . 파이썬에서 타입 힌트는 타입을 검사 할 수 있지만 정적으로 타입이 지정된 언어와는 매우 다른 방식으로 검사됩니다. 파이썬에서 유형 힌트 기능과 관련된 런타임 액세스 할 수있는 데이터 등의 기능을 인수의 예상 유형을 연결하고이 허용 유형을 확인하는. 유형 힌트 구문의 예 :

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.

타입 힌트는 타입을 확인하는 가장 파이썬적인 방법이지만, 타입을 전혀 확인하지 않고 오리 타이핑에 의존하는 것이 더 파이썬적인 경우가 많습니다. 유형 힌트는 비교적 새롭고 배심원은 가장 파이썬적인 솔루션 일 때 여전히 사용 중입니다. 비교적 논쟁의 여지가 없지만 매우 일반적인 비교 : 유형 힌트는 시행 할 수있는 문서 형식을 제공하며, 코드를 조기에 생성하고 오류를 이해하기 쉽게 만들 수 있으며, 오리 입력으로 할 수없는 오류를 포착 할 수 있으며, 비정상적으로 정적 인 검사가 가능합니다 감각이지만 여전히 런타임 외부에 있습니다.) 다른 한편으로, 오리 타이핑은 오랫동안 파이썬 방식이었으며 정적 타이핑의인지 오버 헤드를 부과하지 않으며 덜 장황하며 모든 실행 가능한 유형과 일부를 허용합니다.


2
-1 : mypy는 특히 "정적 유형 검사기"라고 부르므로 "런타임에 유형 검사를 수행해야합니다"를 어디에서 얻었는지 잘 모르겠습니다.
Kevin

@Kevin 돌이켜 보면 그것은 불필요한 불분명했지만 더 많은 것을 얻기 위해 파이썬의 타입 힌트는 런타임 데이터로 바뀌고 그 데이터에 액세스하는 데 mypy사용하는 파이썬 모듈입니다 importlib. 이것이 "정적 유형 검사"인지 여부는 철학적 인 질문이지만 일반 언어 통역사와 수입 기계가 관련되어 있기 때문에 가장 기대되는 것과 다릅니다.
Praxeolitic

4
그것은 사실이 아닙니다. 그것은 사용 하는 자체 typed_ast AST 단지 클론 추가 기능. ast 는 모듈을 가져 오지 않습니다. 그것들을 추상 구문 트리로 파싱합니다.
케빈

18

언제 오리 타이핑이 위험한지 알지 못하고 악한 이유는 다음과 같습니다. 예를 들면 다음과 같습니다. 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()

36
형식 검사를 사용해도 class EvilDuck(Duck)talk ()를 만들고 재정의 할 수 있습니다 . 또는 class ChineseCancerDuck(Duck)몇 년이 지나도 나타나지 않는 심한 부작용이있을 수 있습니다. 당신 : 당신의 아이를 감독 (철저하게 그녀의 장난감을 테스트 더 나을 것
브렛 토마스

36
폭탄이 말을하지 않습니다. 무의미한 방법을 추가하지 마십시오.
rightfold

7
@Dmitry, 이것은 Duck Typing에 대한 일반적인 비판입니다. en.wikipedia.org/wiki/Duck_typing#Criticism ... 당신은 기본적으로 그 의미론이 언어에 의해 강요되지 않는 인터페이스는 악하다고 말합니다. 나는 이것이 자바의 접근 방식이라고 생각합니다. 파이썬의 오리 타이핑의 요점은 특정 인터페이스의 의미에 대해 일반적으로 유지되는 규칙이있을 때만 작동한다는 것입니다. 예를 들어, __file__일반적으로 파일과 같은 객체를 식별하는 데 사용되는 속성 을 재정 의하여 다른 것을 의미 함으로써 많은 Python 코드를 사용할 수 있습니다.
Dan Lenski

2
이 모든 것이 낡은 농담으로 이어집니다. "의사, 내가 이렇게하면 아파요." "그러지 마." "컴파일하면 실행"하는 데 익숙한 사람에게는 불만족 스럽지만, 테스트 강박 관념은 역동적 인 언어 세계에서 나왔습니다.
clacke

1
@clacke 기본적으로 모든 것이 문자열에서 가능한 모든 유형으로 매핑하기 위해 객체이어야하기 때문에 런타임에 유형을 엄격하게 시행하는 것은 너무 비싸고, 덕 타이핑을 사용하면 오리 타이핑을 피할 수 없기 때문에 오리 타이핑을 사용하지 않는 것이 편리합니다. 일반적으로 견고한 인터페이스로는 처리하기가 매우 어렵습니다. 또한 정적 언어는 동적 라이브러리, 평가 및 문자열 화 또는 인터페이스를 통해 오리 타이핑을 작성해야하는 시점에 직면 해 있습니다.
Dmitry

12
isinstance(o, str)

문서에 링크


1
이 링크가 질문에 대한 답변을 제공 할 수 있지만 여기에 답변의 필수 부분을 포함시키고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않을 수 있습니다.
EKons

7

파이썬과 같은 동적 언어를 사용하는 것에 대한 멋진 점은 실제로 그런 것을 확인할 필요가 없다는 것입니다.

객체에서 필요한 메소드를 호출하고을 잡을 것 AttributeError입니다. 나중에 이것으로 다른 (아마 관련이없는) 객체로 메소드를 호출하여 테스트를 위해 객체를 조롱하는 것과 같은 다른 작업을 수행 할 수 있습니다.

객체 와 같은 파일urllib2.urlopen() 을 반환하는 웹에서 데이터를 가져올 때 이것을 많이 사용했습니다 . 이것은 실제 파일 과 동일한 방법을 구현하기 때문에 파일에서 읽는 거의 모든 방법으로 전달 될 수 있습니다 .read()

그러나을 사용할 시간과 장소가 있다고 확신합니다 isinstance(). 그렇지 않으면 아마도 없을 것입니다 :)


이 때의 좋은 예 합니다 동적의 JSON 개체를 구문 분석하는 경우 사용이다. 필드가 문자열 또는 사전인지 미리 알 수 없습니다.
회색

6

더 복잡한 유형 유효성 검사를 위해 파이썬 유형 힌트 주석을 기반으로 유효성을 검사하는 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) 

6

유형의 __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'

고마워, 이것은 사용자에게 피드백으로 표시 할 때 원했던 비밀 코드입니다. ...이 찾는 데 시간이 너무 오래 걸렸다
아론 D. Marasco

5

휴고 :

아마도 list오히려 의미 가 array아니지만 유형 검사의 모든 문제를 지적합니다. 문제의 객체가 목록인지 여부를 알고 싶지 않으며, 어떤 종류의 시퀀스인지 또는 단일 객체인지 알고 싶습니다. 시퀀스처럼 사용하십시오.

기존 시퀀스에 객체를 추가하거나 객체 시퀀스 인 경우 모두 추가

try:
   my_sequence.extend(o)
except TypeError:
  my_sequence.append(o)

문자열 및 / 또는 문자열 시퀀스로 작업하는 경우 한 가지 트릭이 있습니다. 문자열은 종종 단일 객체로 생각되기 때문에 까다 롭지 만 문자 시퀀스이기도합니다. 그보다 더 나쁜 것은 실제로 단일 길이 문자열의 시퀀스이기 때문입니다.

일반적으로 API는 단일 값 또는 시퀀스 만 허용하도록 API를 설계하도록 선택합니다. [ ]필요한 경우 단일 값을 전달할 때 어렵지 않습니다 .

(이것은 문자열처럼 보이기 때문에 문자열에 오류가 발생할 수 있습니다.)


0

유형을 확인하는 간단한 방법은 유형을 알고있는 유형과 비교하는 것입니다.

>>> a  = 1
>>> type(a) == type(1)
True
>>> b = 'abc'
>>> type(b) == type('')
True


-7

주어진 값이 어떤 문자 유형인지 확인하려면 아래 줄을 확인하십시오.

def chr_type(chrx):
    if chrx.isalpha()==True:
        return 'alpha'
    elif chrx.isdigit()==True:
        return 'numeric'
    else:
        return 'nothing'

chr_type("12)

3
이 답변 @Venkatesan을 삭제하지 않으시겠습니까?
회색
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.