python - 클래스 - 파이썬 타입 체크




객체의 유형을 결정 하시겠습니까? (6)

변수가 목록, 사전 또는 다른 것인가를 결정하는 간단한 방법이 있습니까? 두 가지 유형 중 하나 일 수있는 객체를 다시 얻고 있는데 그 차이를 말할 수 있어야합니다.


파이썬 객체의 유형 결정

유형이있는 객체 유형 결정

>>> obj = object()
>>> type(obj)
<class 'object'>

작동하지만, __class__ 와 같은 두 개의 밑줄 속성을 사용하지 마십시오. 이는 의미 론적으로 공개되지 않으며, 아마도이 경우에는 내장 함수가 일반적으로 더 나은 동작을합니다.

>>> obj.__class__ # avoid this!
<class 'object'>

유형 검사

변수가 목록, 사전 또는 다른 것인가를 결정하는 간단한 방법이 있습니까? 두 가지 유형 중 하나 일 수있는 객체를 다시 얻고 있는데 그 차이를 말할 수 있어야합니다.

글쎄 그건 다른 질문인데, 타입 사용 isinstance 사용하지 마십시오 :

def foo(obj):
    """given a string with items separated by spaces, 
    or a list or tuple, 
    do something sensible
    """
    if isinstance(obj, str):
        obj = str.split()
    return _foo_handles_only_lists_or_tuples(obj)

이것은 사용자가 str 을 하위 클래스 화하여 영리하거나 현명한 일을하는 경우를 다룹니다. Liskov Substitution의 원칙에 따라 코드를 위반하지 않고 하위 클래스 인스턴스를 사용할 수 있기를 원하며 isinstance 가이를 지원합니다.

추상화 사용

더 좋게는 collections 또는 numbers 에서 특정 추상 기본 클래스를 찾을 numbers .

from collections import Iterable
from numbers import Number

def bar(obj):
    """does something sensible with an iterable of numbers, 
    or just one number
    """
    if isinstance(obj, Number): # make it a 1-tuple
        obj = (obj,)
    if not isinstance(obj, Iterable):
        raise TypeError('obj must be either a number or iterable of numbers')
    return _bar_sensible_with_iterable(obj)

아니면 명시 적으로 유형 검사를하지 마십시오.

또는, 아마도 가장 중요한 것은 오리 타이핑을 사용하고 코드를 명시 적으로 입력하지 마십시오. 덕 타이핑은 Liskov 대체를보다 우아하고 덜 자세하게 지원합니다.

def baz(obj):
    """given an obj, a dict (or anything with an .items method) 
    do something sensible with each key-value pair
    """
    for key, value in obj.items():
        _baz_something_sensible(key, value)

결론

  • type 을 사용하여 실제로 인스턴스의 클래스를 가져옵니다.
  • isinstance 를 사용하여 실제 서브 클래스 또는 등록 된 추상화를 명시 적으로 점검하십시오.
  • 그리고 그것이 의미가있는 곳에 타입 검사를 피하십시오.

isinstance를 사용하여 조심하십시오.

isinstance(True, bool)
True
>>> isinstance(True, int)
True

그러나 유형

type(True) == bool
True
>>> type(True) == int
False

객체의 인스턴스에는 다음 항목도 있습니다.

__class__

속성. 다음은 Python 3.3 콘솔에서 가져온 샘플입니다.

>>> str = "str"
>>> str.__class__
<class 'str'>
>>> i = 2
>>> i.__class__
<class 'int'>
>>> class Test():
...     pass
...
>>> a = Test()
>>> a.__class__
<class '__main__.Test'>

Python 3.x와 New-Style 클래스 (Python 2.6에서 선택적으로 사용 가능)에서 클래스와 유형이 병합되어 예상치 못한 결과가 나오는 경우가 있습니다. 이러한 이유로 주로 타입 / 클래스를 테스트하는 가장 좋은 방법은 함수에 내장 된 isinstance 입니다.


이전 답변을 제외하고는, 오리 타이핑을 보완하는 몇 가지 추상 기본 클래스 (ABC)를 포함하는 collections.abc 의 존재를 언급 할 가치가 있습니다.

예를 들어, 다음과 같은 항목이 있는지 여부를 명시 적으로 확인하는 대신

isinstance(my_obj, list)

당신은 당신이 가지고있는 객체가 아이템을 얻는 것을 볼 수만 있다면 collections.abc.Sequence 사용할 수 collections.abc.Sequence :

from collections.abc import Sequence
isinstance(my_obj, Sequence) 

항목을 가져오고 설정 하고 삭제할 수있는 객체 (예 : 변경 가능한 시퀀스)에 관심이 있다면 collections.abc.MutableSequence 선택할 수 collections.abc.MutableSequence .

많은 다른 ABC가 정의되어 있으며 맵, Iterable , Callable 등으로 사용할 수있는 객체에 대한 Mapping 이 있습니다. 이 모든 것들의 전체 목록은 collections.abc대한 문서 에서 볼 수 있습니다 .


try ... except 블록을 사용하는 것이 더 Pythonic 일 수 있습니다. 그런 식으로 목록처럼 쓰다듬거나 dict처럼 돌팔이하는 클래스가 있다면 그 타입이 실제로 무엇인지에 관계없이 적절히 행동 할 것입니다.

명확히하기 위해, 변수 유형 사이의 차이를 알려주는 선호하는 방법은 덕 타이핑 ( duck typing )과 관련이 있습니다. 변수가 응답하는 메소드 (및 리턴 유형)가 서브 루틴이 예상하는 것, 예상 한 것과 동일하게 다루는 것 되려고. 예를 들어 브래킷 연산자에 getattrsetattr 을 오버로드하지만 재미있는 내부 체계를 사용하는 클래스가있는 경우에는 에뮬레이트하려는 경우 사전으로 작동하는 것이 적절할 수 있습니다.

type(A) is type(B) 의 또 다른 문제점 type(A) is type(B) 입니다. AB 의 서브 클래스 인 경우 프로그래밍 방식으로 결과가 falsefalse 평가됩니다. 객체가 목록의 하위 클래스 인 경우 목록처럼 작동해야합니다. 다른 답변에 표시된대로 유형을 확인하면이를 방지 할 수 있습니다. (그러나 isinstance 는 작동합니다).


type() 또는 isinstance() 사용할 수 있습니다.

>>> type([]) is list
True

같은 이름의 현재 범위에서 변수를 할당하여 list 이나 다른 유형을 제거 할 수 있다는 경고를받습니다.

>>> the_d = {}
>>> t = lambda x: "aight" if type(x) is dict else "NOPE"
>>> t(the_d) 'aight'
>>> dict = "dude."
>>> t(the_d) 'NOPE'

위에서 우리는 dict 이 문자열로 재 할당되는 것을 봅니다. 그러므로 테스트 :

type({}) is dict

... 실패합니다.

이 문제를 해결하고 type() 주의 깊게 사용하려면 다음을 수행하십시오.

>>> import __builtin__
>>> the_d = {}
>>> type({}) is dict
True
>>> dict =""
>>> type({}) is dict
False
>>> type({}) is __builtin__.dict
True






python