Programing

파이썬에서 객체가 반복 가능한지 어떻게 결정합니까?

lottogame 2020. 9. 28. 07:52
반응형

파이썬에서 객체가 반복 가능한지 어떻게 결정합니까?


같은 방법이 isiterable있습니까? 지금까지 찾은 유일한 해결책은 전화하는 것입니다.

hasattr(myObj, '__iter__')

그러나 이것이 얼마나 어리석은 지 잘 모르겠습니다.


  1. __iter__시퀀스 유형에 대한 작업을 확인 하지만 예를 들어 Python 2의 문자열 에서는 실패합니다 . 나도 정답을 알고 싶습니다. 그때까지 한 가지 가능성이 있습니다 (문자열에서도 작동합니다).

    try:
        some_object_iterator = iter(some_object)
    except TypeError as te:
        print some_object, 'is not iterable'
    

    iter위한 내장 검사 __iter__방법 또는 스트링 인 경우 __getitem__방법.

  2. 또 다른 일반적인 비단뱀 접근 방식은 반복 가능하다고 가정하고 주어진 객체에서 작동하지 않으면 정상적으로 실패하는 것입니다. Python 용어집 :

    그 방법 또는 속성 서명 검사를 통해서가 아니라 어떤 종류의 객체 ( "그것이 보이는 경우에 명시 적 관계에 의해 객체의 유형을 결정하는 파이썬 프로그래밍 스타일 오리 와 같은 꽥꽥 오리 , 그것은해야합니다 오리 강조 인터페이스에 의해.") 특정 유형이 아닌 잘 설계된 코드는 다형성 대체를 허용하여 유연성을 향상시킵니다. 덕 타이핑은 type () 또는 isinstance ()를 사용하는 테스트를 피합니다. 대신, 일반적으로 EAFP (권한보다 용서하기 쉬움) 스타일의 프로그래밍을 사용합니다.

    ...

    try:
       _ = (e for e in my_object)
    except TypeError:
       print my_object, 'is not iterable'
    
  3. collections모듈은 몇 가지 추상 기본 클래스를 제공하여 클래스 나 인스턴스가 특정 기능을 제공하는지 물어볼 수 있습니다. 예를 들면 다음과 같습니다.

    from collections.abc import Iterable
    
    if isinstance(e, Iterable):
        # e is iterable
    

    그러나를 통해 반복 가능한 클래스는 확인하지 않습니다 __getitem__.


오리 타이핑

try:
    iterator = iter(theElement)
except TypeError:
    # not iterable
else:
    # iterable

# for obj in iterator:
#     pass

유형 검사

추상 기본 클래스를 사용합니다 . 최소한 Python 2.6이 필요하며 새로운 스타일의 클래스에서만 작동합니다.

from collections.abc import Iterable   # import directly from collections for Python < 3.3

if isinstance(theElement, Iterable):
    # iterable
else:
    # not iterable

그러나 문서에iter() 설명 대로 좀 더 신뢰할 수 있습니다 .

검사 isinstance(obj, Iterable)는 Iterable로 등록되었거나 __iter__()메소드 가있는 클래스를 감지하지만 메소드로 반복되는 클래스는 감지하지 않습니다 __getitem__(). 객체가 반복 가능한지 확인하는 유일한 방법은를 호출하는 것 iter(obj)입니다.


나는 조금의 상호 작용에 더 많은 빛 비트 창고 싶습니다 iter, __iter__그리고 __getitem__어떤 커튼 뒤에 발생합니다. 그 지식으로 무장하면 왜 최선을 다하는 것인지 이해할 수있을 것입니다.

try:
    iter(maybe_iterable)
    print('iteration will probably work')
except TypeError:
    print('not iterable')

먼저 사실을 나열한 다음 for파이썬에서 루프 를 사용할 때 어떤 일이 발생하는지에 대한 빠른 알림을 받은 다음 사실을 설명하기위한 토론이 이어집니다.

사리

  1. 당신은 어떤 개체에서 반복자를 얻을 수 있습니다 o호출하여 iter(o)다음 조건 중 하나 이상이 사실이 보유하고있는 경우

    )를 o__iter__반복자 객체를 반환하는 방법을. 반복자는 __iter____next__(Python 2 :) next메서드 가있는 모든 개체입니다 .

    b) o갖는 __getitem__방법.

  2. Iterable또는 의 인스턴스를 Sequence확인하거나 속성을 확인하는 __iter__것만으로는 충분하지 않습니다.

  3. 객체의 경우 o구현은 __getitem__아니지만 __iter__, iter(o)시도로부터 아이템을 취득하는 것을 반복자 구성합니다 o인덱스 0에서 시작하는 정수 인덱스를 반복자는 잡을 것 IndexError제기입니다 (하지만 다른 오류를) 다음 제기 StopIteration자체를.

  4. 가장 일반적인 의미에서에서 반환 된 반복기 iter가 정상 인지 확인하는 것 외에는 시도 할 방법이 없습니다.

  5. 객체가를 o구현 __iter__하면 iter함수는에서 반환 된 객체 __iter__가 반복자 인지 확인 합니다. 객체가를 구현하는 경우에는 온 전성 검사가 없습니다 __getitem__.

  6. __iter__승리합니다. 객체의 경우 o구현 모두 __iter__하고 __getitem__, iter(o)호출합니다 __iter__.

  7. 자신의 객체를 반복 가능하게 만들려면 항상 추상 기본 클래스 Iterable 또는 하위 클래스 중 하나에서 상속하십시오. __iter__메서드 를 구현해야합니다. 그렇지 않으면의 경우와 같이 제공됩니다 Sequence.

for 루프

따라하기 위해서는 forPython 에서 루프 를 사용할 때 어떤 일이 발생하는지 이해해야 합니다. 이미 알고있는 경우 다음 섹션으로 바로 건너 뛰어도됩니다.

for item in o일부 반복 가능한 객체에 사용할 때 oPython iter(o)은 반복기 객체를 반환 값으로 호출 하고 기대합니다. 반복자는 __next__(또는 nextPython 2에서) 메서드와 메서드 를 구현하는 모든 객체입니다 __iter__.

관례에 따라 __iter__반복자 메서드는 객체 자체를 반환해야합니다 (예 :) return self. 그런 다음 Python next은가 발생할 때까지 반복기 를 호출 합니다 StopIteration. 이 모든 작업은 암시 적으로 발생하지만 다음 데모에서는이를 볼 수 있습니다.

import random

class DemoIterable(object):
    def __iter__(self):
        print('__iter__ called')
        return DemoIterator()

class DemoIterator(object):
    def __iter__(self):
        return self

    def __next__(self):
        print('__next__ called')
        r = random.randint(1, 10)
        if r == 5:
            print('raising StopIteration')
            raise StopIteration
        return r

반복 DemoIterable:

>>> di = DemoIterable()
>>> for x in di:
...     print(x)
...
__iter__ called
__next__ called
9
__next__ called
8
__next__ called
10
__next__ called
3
__next__ called
10
__next__ called
raising StopIteration

토론 및 삽화

포인트 1과 2에서 : 반복기 및 신뢰할 수없는 검사 얻기

다음 클래스를 고려하십시오.

class BasicIterable(object):
    def __getitem__(self, item):
        if item == 3:
            raise IndexError
        return item

구현 하기 때문에 iter의 인스턴스를 사용하여 호출 BasicIterable하면 문제없이 반복기가 반환됩니다 .BasicIterable__getitem__

>>> b = BasicIterable()
>>> iter(b)
<iterator object at 0x7f1ab216e320>

그러나 속성이 없으며 or 의 인스턴스로 간주 b되지 않는다는 점에 유의 해야합니다 .__iter__IterableSequence

>>> from collections import Iterable, Sequence
>>> hasattr(b, '__iter__')
False
>>> isinstance(b, Iterable)
False
>>> isinstance(b, Sequence)
False

이것이 Luciano Ramalho의 Fluent Python 이 객체가 반복 가능한지 확인하는 가장 정확한 방법으로 iter잠재력 TypeError호출 하고 처리하도록 권장하는 이유 입니다. 책에서 직접 인용 :

Python 3.4에서 객체 x가 반복 가능한지 확인하는 가장 정확한 방법 은 그렇지 않은 경우 예외 를 호출 iter(x)하고 처리하는 TypeError것입니다. ABC는 그렇지 않은 반면 레거시 방법 도 고려 isinstance(x, abc.Iterable)하기 때문에를 사용하는 것보다 더 정확 합니다.iter(x)__getitem__Iterable

요점 3 :을 제공 __getitem__하지만 제공 하지 않는 객체에 대한 반복__iter__

BasicIterable예상대로 작업 인스턴스에 대해 반복 : Python은 0부터 시작하여 색인별로 항목을 가져 오려고 시도하는 반복기를 생성합니다 IndexError. 데모 개체의 __getitem__방법은 단순히 반환 item에 인수로 제공 한을 __getitem__(self, item)반복자에 의해 반환에 의해 iter.

>>> b = BasicIterable()
>>> it = iter(b)
>>> next(it)
0
>>> next(it)
1
>>> next(it)
2
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

이터레이터 StopIteration는 다음 항목을 반환 할 수 없을 때 IndexError발생하고 발생 item == 3하는는 내부적으로 처리됩니다. 이상 반복하는 이유입니다 BasicIterableA를 for예상대로 루프 작동 :

>>> for x in b:
...     print(x)
...
0
1
2

이터레이터 iter가 인덱스로 항목에 액세스하려고 시도 하는 방식에 대한 개념을 설명하기위한 또 다른 예가 있습니다. WrappedDict에서 상속하지 않으므로 dict인스턴스에 __iter__메서드 가 없습니다 .

class WrappedDict(object): # note: no inheritance from dict!
    def __init__(self, dic):
        self._dict = dic

    def __getitem__(self, item):
        try:
            return self._dict[item] # delegate to dict.__getitem__
        except KeyError:
            raise IndexError

__getitem__dict.__getitem__대한 호출 대괄호 표기법이 단순히 속기 인 위임됩니다 .

>>> w = WrappedDict({-1: 'not printed',
...                   0: 'hi', 1: 'StackOverflow', 2: '!',
...                   4: 'not printed', 
...                   'x': 'not printed'})
>>> for x in w:
...     print(x)
... 
hi
StackOverflow
!

지점 4와 5에서 : 다음 iter을 호출 할 때 반복자를 확인합니다__iter__ .

iter(o)객체에 대해 호출 o, iter의 반환 값이 있는지 확인합니다 __iter__방법이 존재하는 경우, 반복자입니다. 이는 반환 된 객체가 __next__(또는 nextPython 2에서) 및 __iter__. iter을 (를) 제공하는 객체에 대한 온 전성 검사를 수행 할 수 없습니다. 이는 객체 __getitem__의 항목이 정수 인덱스로 액세스 할 수 있는지 여부를 확인할 방법이 없기 때문입니다.

class FailIterIterable(object):
    def __iter__(self):
        return object() # not an iterator

class FailGetitemIterable(object):
    def __getitem__(self, item):
        raise Exception

FailIterIterable인스턴스 에서 반복기를 생성 하면 즉시 실패하고 반복기를 생성 FailGetItemIterable하면 성공하지만 .NET에 대한 첫 번째 호출에서 예외가 발생합니다 __next__.

>>> fii = FailIterIterable()
>>> iter(fii)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: iter() returned non-iterator of type 'object'
>>>
>>> fgi = FailGetitemIterable()
>>> it = iter(fgi)
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/path/iterdemo.py", line 42, in __getitem__
    raise Exception
Exception

포인트 6 : __iter__승리

이것은 간단합니다. 객체가 구현하는 경우 __iter____getitem__, iter호출합니다 __iter__. 다음 클래스를 고려하십시오

class IterWinsDemo(object):
    def __iter__(self):
        return iter(['__iter__', 'wins'])

    def __getitem__(self, item):
        return ['__getitem__', 'wins'][item]

인스턴스를 반복 할 때 출력 :

>>> iwd = IterWinsDemo()
>>> for x in iwd:
...     print(x)
...
__iter__
wins

요점 7 : 반복 가능한 클래스는 구현해야합니다. __iter__

왜 대부분의 내장 시퀀스 가 충분할 때 메소드를 list구현 하는지 스스로 물어볼 수 있습니다 .__iter____getitem__

class WrappedList(object): # note: no inheritance from list!
    def __init__(self, lst):
        self._list = lst

    def __getitem__(self, item):
        return self._list[item]

결국, 반복 대표 호출 할 수있는 위 클래스의 인스턴스 이상 __getitem__list.__getitem__(대괄호 표기법을 사용하여) 잘 작동합니다 :

>>> wl = WrappedList(['A', 'B', 'C'])
>>> for x in wl:
...     print(x)
... 
A
B
C

커스텀 iterable이 구현해야하는 이유 __iter__는 다음과 같습니다.

  1. 를 구현 __iter__하면 인스턴스가 반복 가능한 것으로 간주되고을 isinstance(o, collections.abc.Iterable)반환 True합니다.
  2. 에서 반환 된 객체 __iter__가 반복자가 아닌 경우 iter즉시 실패하고 TypeError.
  3. __getitem__이전 버전과의 호환성을 위해 특수 처리가 존재합니다. Fluent Python에서 다시 인용 :

이것이 모든 파이썬 시퀀스가 ​​반복 가능한 이유입니다 : 모두 __getitem__. 사실, 표준 시퀀스도 구현 __iter__하고 당신 도 구현 해야합니다.의 특수 처리는 __getitem__이전 버전과의 호환성을 위해 존재하고 나중에 사라질 수 있기 때문입니다 (이 글을 쓸 때 더 이상 사용되지는 않지만).


이것으로는 충분하지 않습니다.에서 반환 된 객체 __iter__는 반복 프로토콜 (즉, next메서드)을 구현해야합니다 . 설명서 의 관련 섹션을 참조하십시오 .

Python에서 좋은 방법은 "확인"대신 "시도하고 보는"것입니다.


Python <= 2.5에서는 할 수없고해서는 안됩니다. iterable은 "비공식적 인"인터페이스였습니다.

그러나 Python 2.6 및 3.0부터는 collections 모듈에서 사용할 수있는 일부 내장 ABC와 함께 새로운 ABC (추상 기본 클래스) 인프라를 활용할 수 있습니다.

from collections import Iterable

class MyObject(object):
    pass

mo = MyObject()
print isinstance(mo, Iterable)
Iterable.register(MyObject)
print isinstance(mo, Iterable)

print isinstance("abc", Iterable)

이제 이것이 바람직하든 실제로 작동하든 관습에 불과합니다. 보시다시피 반복 불가능한 객체를 Iterable로 등록 수 있습니다. 그러면 런타임에 예외가 발생합니다. 따라서 isinstance는 "새로운"의미를 얻습니다. "선언 된"유형 호환성을 확인하기 만하면 파이썬으로 이동하는 좋은 방법입니다.

반면에 객체가 필요한 인터페이스를 충족하지 않으면 어떻게 하시겠습니까? 다음 예를 살펴보십시오.

from collections import Iterable
from traceback import print_exc

def check_and_raise(x):
    if not isinstance(x, Iterable):
        raise TypeError, "%s is not iterable" % x
    else:
        for i in x:
            print i

def just_iter(x):
    for i in x:
        print i


class NotIterable(object):
    pass

if __name__ == "__main__":
    try:
        check_and_raise(5)
    except:
        print_exc()
        print

    try:
        just_iter(5)
    except:
        print_exc()
        print

    try:
        Iterable.register(NotIterable)
        ni = NotIterable()
        check_and_raise(ni)
    except:
        print_exc()
        print

객체가 예상 한 내용을 충족하지 않으면 TypeError가 발생하지만 적절한 ABC가 등록 된 경우 검사는 유용하지 않습니다. 반대로 __iter__메서드를 사용할 수있는 경우 Python은 해당 클래스의 객체를 Iterable로 자동 인식합니다.

따라서 반복 가능한 것을 기대하는 경우 반복하고 잊어 버리십시오. 반면에 입력 유형에 따라 다른 작업을 수행해야하는 경우 ABC 인프라가 매우 유용 할 수 있습니다.


try:
  #treat object as iterable
except TypeError, e:
  #object is not actually iterable

당신의 오리가 정말로 오리인지 확인하기 위해 검사를 실행하지 말고 그것이 반복 가능한지 아닌지 확인하고, 그것이있는 것처럼 취급하고 그렇지 않은 경우 불평하십시오.


지금까지 찾은 최고의 솔루션 :

hasattr(obj, '__contains__')

기본적으로 객체가 in연산자를 구현하는지 확인합니다 .

장점 (다른 솔루션에는 세 가지가 모두 없음) :

  • 그것은 표현식입니다 ( try ... except 변형 과 달리 lambda 로 작동합니다 )
  • 그것이 포함한 모든 반복 가능 객체에 의해 구현 (한다)는 스트링 (반대 __iter__)
  • 모든 Python> = 2.5에서 작동

메모:

  • "권한이 아닌 용서 요청"이라는 파이썬 철학은 예를 들어 목록에서 반복 가능 항목과 반복 불가능 항목이 모두 있고 유형에 따라 각 요소를 다르게 처리해야하는 경우 제대로 작동하지 않습니다 (try 및 non- 예외적으로 iterables 작동하지만 엉덩이가 추하고 오해의 소지가 있습니다)
  • 반복 가능한지 확인하기 위해 객체 (예 : [x for x in obj])를 실제로 반복하려고 시도하는이 문제에 대한 솔루션은 큰 이터 러블에 대해 상당한 성능 페널티를 유발할 수 있습니다 (특히 이터 러블의 처음 몇 요소 만 필요한 경우, 예) 피해야합니다

이것을 시도해 볼 수 있습니다.

def iterable(a):
    try:
        (x for x in a)
        return True
    except TypeError:
        return False

반복되는 생성기를 만들 수 있다면 (하지만 생성기를 사용하지 않아 공간을 차지하지 않음) 반복 가능합니다. "duh"종류의 것 같습니다. 처음에 변수가 반복 가능한지 확인해야하는 이유는 무엇입니까?


Python 3.5 부터 유형 관련 항목에 대해 표준 라이브러리의 유형 지정 모듈을 사용할 수 있습니다 .

from typing import Iterable

...

if isinstance(my_item, Iterable):
    print(True)

여기 에서 좋은 해결책을 찾았 습니다 .

isiterable = lambda obj: isinstance(obj, basestring) \
    or getattr(obj, '__iter__', False)

Python 2 Glossary 에 따르면 반복 가능 항목은 다음과 같습니다.

모든 시퀀스 유형 (예 : list, strtuple)과 dictfile및 및 __iter__()또는 __getitem__()메서드로 정의한 모든 클래스의 객체와 같은 일부 비 시퀀스 유형 . Iterables는 for 루프와 시퀀스가 ​​필요한 다른 많은 장소 (zip (), map (), ...)에서 사용할 수 있습니다. 반복 가능한 객체가 내장 함수 iter ()에 인수로 전달되면 객체의 반복자를 반환합니다.

물론,“허가보다 용서를 구하는 것이 더 쉽다”는 사실을 기반으로 한 파이썬의 일반적인 코딩 스타일을 감안할 때 일반적인 기대는 사용하는 것입니다.

try:
    for i in object_in_question:
        do_something
except TypeError:
    do_something_for_non_iterable

그러나 명시 적으로 확인해야하는 경우 .NET에서 iterable을 테스트 할 수 있습니다 hasattr(object_in_question, "__iter__") or hasattr(object_in_question, "__getitem__"). strs에는 __iter__메서드 없기 때문에 (적어도 Python 2에는없고 Python 3에서는 그렇습니다) generator객체에 메서드 없기 때문에 둘 다 확인해야합니다 __getitem__.


종종 스크립트 내에서 iterable함수 를 정의하는 것이 편리하다는 것을 알게 됩니다. (이제 Alfe의 제안 된 단순화를 통합합니다) :

import collections

def iterable(obj):
    return isinstance(obj, collections.Iterable):

그래서 어떤 객체가 매우 읽기 쉬운 형태로 반복 가능한지 테스트 할 수 있습니다.

if iterable(obj):
    # act on iterable
else:
    # not iterable

callable함수를 사용하는 것처럼

편집 : numpy가 설치되어 있으면 간단히 할 수 있습니다 : from numpy import iterable, 이것은 단순히 다음과 같습니다.

def iterable(obj):
    try: iter(obj)
    except: return False
    return True

numpy가없는 경우이 코드 또는 위의 코드를 구현할 수 있습니다.


에는 다음과 같은 내장 기능이 있습니다.

from pandas.util.testing import isiterable

def is_iterable(x):
    try:
        0 in x
    except TypeError:
        return False
    else:
        return True

이것은 모든 반복 가능한 객체에 대해 예 라고 말하지만 Python 2의 문자열에는 아니오라고 말합니다 . (예를 들어 재귀 함수가 문자열이나 문자열 컨테이너를 취할 수있을 때 제가 원하는 것입니다. 그런 상황에서 용서 를 구하면 난독 코드가 발생할 수 있으며 먼저 권한을 요청하는 것이 좋습니다.)

import numpy

class Yes:
    def __iter__(self):
        yield 1;
        yield 2;
        yield 3;

class No:
    pass

class Nope:
    def __iter__(self):
        return 'nonsense'

assert is_iterable(Yes())
assert is_iterable(range(3))
assert is_iterable((1,2,3))   # tuple
assert is_iterable([1,2,3])   # list
assert is_iterable({1,2,3})   # set
assert is_iterable({1:'one', 2:'two', 3:'three'})   # dictionary
assert is_iterable(numpy.array([1,2,3]))
assert is_iterable(bytearray("not really a string", 'utf-8'))

assert not is_iterable(No())
assert not is_iterable(Nope())
assert not is_iterable("string")
assert not is_iterable(42)
assert not is_iterable(True)
assert not is_iterable(None)

여기에있는 다른 많은 전략은 현에 예라고 말할 것입니다. 그것이 당신이 원하는 것이라면 사용하십시오.

import collections
import numpy

assert isinstance("string", collections.Iterable)
assert isinstance("string", collections.Sequence)
assert numpy.iterable("string")
assert iter("string")
assert hasattr("string", '__getitem__')

참고 : is_iterable ()은 bytes유형의 문자열에 대해 yes라고 표시합니다 bytearray.

  • bytesPython 3의 객체는 반복 가능 True == is_iterable(b"string") == is_iterable("string".encode('utf-8'))합니다. Python 2에는 이러한 유형이 없습니다.
  • bytearray Python 2 및 3의 객체는 반복 가능합니다. True == is_iterable(bytearray(b"abc"))

OP hasattr(x, '__iter__')접근 방식은 Python 3의 문자열에 대해 yes라고 말하고 Python 2에서는 no로 표시합니다 ( ''또는 b''또는 여부에 관계없이 u''). @LuisMasuelli에게 감사드립니다 __iter__.


파이썬이 왜 가지고 있는지 항상 알 수 callable(obj) -> bool없지만 iterable(obj) -> bool...
확실히 hasattr(obj,'__call__')느리더라도 수행하기가 더 쉽습니다 .

거의 모든 다른 답변에서 try/ 사용을 권장하기 때문에 except TypeError예외 테스트는 일반적으로 모든 언어에서 나쁜 관행으로 간주되므로 여기에 iterable(obj) -> bool내가 더 좋아하고 자주 사용 하는 구현이 있습니다.

파이썬 2의 위해, 나는 ... 그냥 여분의 성능 향상을 위해 람다를 사용합니다
(파이썬 3에서 당신이 함수를 정의하는 데 사용할 중요하지 않습니다 def과 거의 같은 속도가 lambda)

iterable = lambda obj: hasattr(obj,'__iter__') or hasattr(obj,'__getitem__')

이 함수는를 __iter__테스트하지 않기 때문에 객체에 대해 더 빠르게 실행 됩니다 __getitem__.

대부분의 반복 가능한 객체는 __iter__특별한 경우 객체가로 돌아가는 위치에 의존해야 __getitem__하지만 객체가 반복 가능하려면 둘 중 하나가 필요합니다.
(그리고 이것은 표준이므로 C 객체에도 영향을 미칩니다)


파이썬의 덕 타이핑을 존중하는 가장 쉬운 방법 은 오류를 잡는 것입니다 (파이썬은 객체가 반복자가 될 것으로 기대하는 것을 완벽하게 알고 있습니다) :

class A(object):
    def __getitem__(self, item):
        return something

class B(object):
    def __iter__(self):
        # Return a compliant iterator. Just an example
        return iter([])

class C(object):
    def __iter__(self):
        # Return crap
        return 1

class D(object): pass

def iterable(obj):
    try:
        iter(obj)
        return True
    except:
        return False

assert iterable(A())
assert iterable(B())
assert iterable(C())
assert not iterable(D())

참고 :

  1. 객체가 반복 불가능한지 또는 __iter__예외 유형이 동일한 경우 버그 가 구현 되었는지 여부는 구별과 관련이 없습니다 . 어쨌든 객체를 반복 할 수 없습니다.
  2. 나는 당신의 우려를 이해한다고 생각합니다. 내 개체에 대해 정의되지 않은 if를 발생 callable시키기 위해 덕 타이핑에 의존 할 수 있다면 검사로 어떻게 존재 하지만 반복 가능한 검사의 경우는 그렇지 않습니까?AttributeError__call__

    나는 대답을 모르지만, 내가 (및 다른 사용자) 제공 한 함수를 구현하거나 코드에서 예외를 포착 할 수 있습니다 (해당 부분의 구현은 내가 작성한 함수와 같을 것입니다. 나머지 코드에서 반복자 생성을 통해 예외를 캡처하고 다른 TypeError.


isiterable다음 코드 func는 True객체가 반복 가능한 경우 반환 합니다. 반복 할 수없는 경우 반환False

def isiterable(object_):
    return hasattr(type(object_), "__iter__")

fruits = ("apple", "banana", "peach")
isiterable(fruits) # returns True

num = 345
isiterable(num) # returns False

isiterable(str) # returns False because str type is type class and it's not iterable.

hello = "hello dude !"
isiterable(hello) # returns True because as you know string objects are iterable

__iter__속성 을 확인하는 대신 __len__문자열을 포함하여 모든 파이썬 내장 iterable에 의해 구현되는 속성을 확인할 수 있습니다.

>>> hasattr(1, "__len__")
False
>>> hasattr(1.3, "__len__")
False
>>> hasattr("a", "__len__")
True
>>> hasattr([1,2,3], "__len__")
True
>>> hasattr({1,2}, "__len__")
True
>>> hasattr({"a":1}, "__len__")
True
>>> hasattr(("a", 1), "__len__")
True

반복 불가능한 객체는 명백한 이유로 이것을 구현하지 않습니다. 그러나이를 구현하지 않는 사용자 정의 이터 러블이나 iter처리 할 수 있는 생성기 표현식은 포착하지 않습니다 . 그러나 이것은 한 줄로 수행 할 수 있으며 or생성기에 대한 간단한 표현식 검사를 추가하면 이 문제를 해결할 수 있습니다. (쓰기 type(my_generator_expression) == generatorNameError. 대신 답변을 참조하십시오 .)

다음 유형에서 GeneratorType을 사용할 수 있습니다.

>>> import types
>>> types.GeneratorType
<class 'generator'>
>>> gen = (i for i in range(10))
>>> isinstance(gen, types.GeneratorType)
True

--- utdemir가 수락 한 답변

(이것은 len객체를 호출 할 수 있는지 확인하는 데 유용합니다 .)


파티에 좀 늦었지만 나는 스스로에게이 질문을했고 이것이 답을 생각하는 것을 보았다. 누군가가 이미 이것을 게시했는지 모르겠습니다. 그러나 본질적으로 모든 반복 가능한 유형은 dict에 " getitem " 이 있음을 알았습니다 . 이것은 시도하지 않고도 객체가 반복 가능한지 확인하는 방법입니다. (펀 의도)

def is_attr(arg):
    return '__getitem__' in dir(arg)

실제로 "올바른" 것은 아니지만 문자열, 튜플, 부동 소수점 등과 같은 가장 일반적인 유형의 빠른 검사 역할을 할 수 있습니다.

>>> '__iter__' in dir('sds')
True
>>> '__iter__' in dir(56)
False
>>> '__iter__' in dir([5,6,9,8])
True
>>> '__iter__' in dir({'jh':'ff'})
True
>>> '__iter__' in dir({'jh'})
True
>>> '__iter__' in dir(56.9865)
False

참고 URL : https://stackoverflow.com/questions/1952464/in-python-how-do-i-determine-if-an-object-is-iterable

반응형