etc./StackOverFlow

Python에서 객체가 반복 가능한지 어떻게 확인합니까?

청렴결백한 만능 재주꾼 2023. 4. 28. 04:06
반응형

질문자 :willem


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

 hasattr(myObj, '__iter__')

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



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

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

    iter 내장은 __iter__ 메서드 또는 문자열의 경우 __getitem__ 메서드를 확인합니다.

  2. 또 다른 일반적인 파이썬 접근 방식은 iterable을 가정한 다음 주어진 객체에서 작동하지 않으면 정상적으로 실패하는 것입니다. 파이썬 용어집:

    그 방법 또는 속성 서명 검사를 통해서가 아니라 강조 인터페이스에 의해 어떤 종류의 객체 ( "오리처럼 외모와 오리처럼 꽥꽥 경우, 오리해야합니다.")에 명시 적 관계에 의해 객체의 유형을 결정하는 파이썬 프로그래밍 스타일 특정 유형이 아닌 잘 설계된 코드는 다형성 대체를 허용하여 유연성을 향상시킵니다. 덕 타이핑은 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__ 통해 반복 가능한 클래스를 확인하지 않습니다.


miku

오리 타이핑

 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) 를 호출하는 것입니다.


Georg Schölly

iter , __iter____getitem__ 의 상호 작용과 커튼 뒤에서 일어나는 일에 대해 좀 더 자세히 설명하고 싶습니다. 그 지식으로 무장하면, 당신이 할 수 있는 최선의 이유를 이해할 수 있을 것입니다.

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

for 루프를 사용할 때 어떤 일이 발생하는지에 대한 빠른 알림과 함께 사실을 설명하기 위한 토론이 이어집니다.

사리

  1. 다음 조건 중 하나 이상이 참이면 iter(o) 를 호출 o 에서 반복자를 얻을 수 있습니다.

    a) o 에는 반복자 객체를 반환하는 __iter__ __iter____next__ (Python 2: next ) 메서드가 있는 모든 객체입니다.

    b) o 에는 __getitem__ 메서드가 있습니다.

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

  3. 객체 o __getitem__ 만 구현하고 __iter__ 구현하지 않는 경우 iter(o) 는 인덱스 0에서 시작하여 정수 인덱스 o 에서 항목을 가져 IndexError 발생 StopIteration 다음 StopIteration 자체를 발생시킵니다.

  4. iter 가 반환한 iterator가 정상적인지 확인할 수 있는 방법은 시도하는 것 외에는 없습니다.

  5. 객체 o__iter__ 구현하면 iter __iter__ 가 반환한 객체가 반복자인지 확인합니다. __getitem__ 만 구현하는 경우 온전성 검사가 없습니다.

  6. __iter__ 이깁니다. 객체 o __iter____getitem__ 모두 구현하면 iter(o) __iter__ 를 호출합니다.

  7. 자신의 객체를 반복 가능하게 만들고 싶다면 항상 __iter__ 메서드를 구현하세요.

루프를 for

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

당신이 사용하는 경우 for item in o 몇 가지 반복 가능한 객체에 대한 o , 파이썬은 호출 iter(o) 반환 값으로 반복자 객체를 기대하고있다. __next__ (또는 Python 2에서는 next __iter__ 메서드를 구현하는 모든 객체입니다.

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

 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>

그러나 b 에는 __iter__ Iterable 또는 Sequence 의 인스턴스로 간주되지 않습니다.

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

이것이 Luciano Ramalho의 Fluent Python 이 객체가 반복 가능한지 확인하는 가장 정확한 방법으로 iter 호출하고 잠재적인 TypeError 책에서 직접 인용:

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

__getitem__ __iter__ 는 제공하지 않는 객체에 대한 반복

BasicIterable 의 인스턴스에 대한 반복 IndexError 가 발생할 때까지 0에서 시작하여 인덱스별로 항목을 가져오려고 시도하는 반복기를 생성합니다. 데모 객체의 __getitem__ iter 반환한 반복자 __getitem__(self, item) 에 인수로 제공 item 을 단순히 반환합니다.

 >>> 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

iterator는 다음 항목을 반환할 수 없을 때 StopIteration item == 3 대해 발생 IndexError 는 내부적으로 처리됩니다. for 루프를 사용하여 BasicIterable 을 반복하는 것이 예상대로 작동하는 이유입니다.

 >>> 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__ (또는 Python 2에서는 next __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 __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__

__getitem__ 이면 충분할 list __iter__ 메서드를 구현하는 이유를 스스로에게 물어볼 수 있습니다.

 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

__iter__ 를 구현해야 하는 이유는 다음과 같습니다.

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

이것이 모든 Python 시퀀스가 반복 가능한 이유입니다. __getitem__ 사실, 표준 시퀀스는 __iter__ 도 구현하고 여러분의 것도 그렇게 해야 합니다. __getitem__ 의 특별한 처리는 이전 버전과의 호환성을 위해 존재하고 앞으로 사라질 수 있기 때문입니다(이 글을 쓰는 동안 더 이상 사용되지 않음).


timgeb

나는 최근에 이 문제를 꽤 많이 연구하고 있다. 내 결론에 따르면 요즘에는 이것이 최선의 접근 방식입니다.

 from collections.abc import Iterable # drop `.abc` with Python 2.7 or lower def iterable(obj): return isinstance(obj, Iterable)

위의 내용은 이미 이전에 권장되었지만 iter() 를 사용하는 것이 더 낫다는 일반적인 합의가 있었습니다.

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

iter() 를 사용 __getitem__ 만 반복 가능한 것으로 간주되는 객체에 점점 짜증이 나기 시작했습니다. __getitem__ 이 있어야 하는 타당한 이유가 있으며 그와 함께 위의 코드가 제대로 작동하지 않습니다. 실생활의 예로 Faker 를 사용할 수 있습니다. 위의 코드는 반복 가능하다고 보고하지만 실제로 반복하려고 하면 AttributeError 발생합니다(Faker 4.0.2에서 테스트됨):

 >>> from faker import Faker >>> fake = Faker() >>> iter(fake) # No exception, must be iterable <iterator object at 0x7f1c71db58d0> >>> list(fake) # Ooops Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/.../site-packages/faker/proxy.py", line 59, in __getitem__ return self._factory_map[locale.replace('-', '_')] AttributeError: 'int' object has no attribute 'replace'

insinstance() 사용한다면 실수로 Faker 인스턴스(또는 __getitem__ 만 있는 다른 객체)를 반복 가능한 것으로 간주하지 않을 것입니다.

 >>> from collections.abc import Iterable >>> from faker import Faker >>> isinstance(Faker(), Iterable) False

이전 답변에서는 Python에서 반복을 구현하는 이전 방법이 __getitem__ 을 기반으로 하고 isinstance() 접근 방식이 이를 감지하지 못하기 때문에 iter() 를 사용하는 것이 더 안전하다고 언급했습니다. 이것은 오래된 Python 버전에서 사실일 수 있지만, 나의 철저한 테스트를 기반으로 하는 isinstance() 는 요즘 잘 작동합니다. isinstance() 가 작동하지 않았지만 iter() 가 작동한 유일한 경우 UserDict 를 사용하는 것이었습니다. 관련이 있는 경우 isinstance(item, (Iterable, UserDict)) 를 사용하여 이를 처리할 수 있습니다.


Pekka Klärck

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

 from typing import Iterable ... if isinstance(my_item, Iterable): print(True)

Rotareti

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

Python에서는 "확인" 대신 "시도하고 확인"하는 것이 좋습니다.


jldupont

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

그러나 Python 2.6 및 3.0부터 컬렉션 모듈에서 사용할 수 있는 일부 내장 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는 "새로운" 의미를 얻습니다. "선언된" 유형 호환성을 확인하기만 하면 됩니다. 이는 Python에서 사용하기에 좋은 방법입니다.

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

 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로 자동 인식합니다.

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


Alan Franzoni

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

오리가 정말 오리인지 확인하기 위해 검사를 실행하여 반복 가능한지 여부를 확인하지 말고 있는 것처럼 처리하고 그렇지 않은 경우 불평하십시오.


badp

당신은 이것을 시도할 수 있습니다:

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

반복하는 생성기를 만들 수 있다면(그러나 생성기를 사용하지 않아 공간을 차지하지 않음), 반복 가능합니다. '으음' 그런 것 같습니다. 처음에 변수가 반복 가능한지 확인해야 하는 이유는 무엇입니까?


Chris Lutz

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

hasattr(obj, '__contains__')

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

장점 (다른 솔루션에는 세 가지 모두가 포함되어 있지 않음):

  • 그것은 표현식입니다( try...except 변형과 반대로 람다로 작동)
  • __iter__ 와 반대되는) 문자열을 포함하여 모든 iterable에 의해 구현되어야 합니다 (반드시)
  • 모든 Python에서 작동 >= 2.5

노트:

  • "허가가 아니라 용서를 구하라"라는 파이썬 철학은 예를 들어 목록에 반복 가능 항목과 반복 가능 항목이 모두 있고 각 요소를 유형에 따라 다르게 처리해야 할 때 잘 작동하지 않습니다(try 및 non-it에서 반복 가능 처리). iterables on except 작동하지만, 보기 흉하고 오해의 소지가 있습니다)
  • 객체가 반복 가능한지 확인하기 위해 객체(예: [x for x in obj])에 대해 실제로 반복을 시도하는 이 문제에 대한 솔루션은 대규모 반복 가능 항목에 대해 상당한 성능 저하를 유발할 수 있습니다(특히 반복 가능 항목의 처음 몇 개 요소만 필요한 경우, 예) 피해야 합니다.

Vlad

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

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

jbochi

Python 2 Glossary 에 따르면 iterable은 다음과 같습니다.

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

물론, "허가보다 용서를 구하는 것이 더 쉽다"는 사실에 기반한 Python의 일반적인 코딩 스타일을 감안할 때 일반적인 기대는 다음을 사용하는 것입니다.

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

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


Anaphory

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가 없으면 이 코드나 위의 코드를 간단히 구현할 수 있습니다.


fmonegaglia

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

 from pandas.util.testing import isiterable

Soren

callable(obj) -> bool 있지만 iterable(obj) -> bool 없는 이유에 대해 항상 이해하지 못했습니다.
hasattr(obj,'__call__') 을 수행하는 것이 더 쉽습니다.

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

파이썬 2를 위해 추가 성능 향상을 위해 람다를 사용할 것입니다...
(python 3에서는 함수를 정의하는 데 무엇을 사용하는지는 중요하지 않습니다. def lambda 와 거의 같은 속도를 가집니다)

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

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

대부분의 반복 가능한 객체는 특수 케이스 객체가 __getitem__ __iter__ 의존해야 하지만 객체가 반복 가능하려면 둘 중 하나가 필요합니다.
(그리고 이것이 표준이기 때문에 C 객체에도 영향을 미칩니다)


Tcll

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

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

 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__')

bytesbytearray 유형의 문자열에 대해 yes라고 말합니다.

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

OP hasattr(x, '__iter__') 접근 방식은 Python 3에서는 문자열에 대해 yes, Python 2에서는 no라고 말합니다( '' 또는 b'' 또는 u'' 여부에 관계없이). @LuisMasuelli 덕분에 버그가 있는 __iter__ 도 실망하게 됩니다.


Bob Stein

Python의 오리 타이핑을 존중하는 가장 쉬운 방법은 오류를 잡는 것입니다(Python은 객체가 반복자가 되기 위해 무엇을 기대하는지 완벽하게 알고 있습니다).

 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. 어떻게 : 나는 당신의 우려를 이해 생각 callable 나는 또한 인상 오리 입력에 의존 할 수 있다면 체크로 존재 AttributeError 하는 경우 __call__ 내 개체에 대해 정의되지 않은,하지만 반복 가능한 검사의 경우이 아니다?

    나는 대답을 모르지만 내가 (및 다른 사용자)가 제공한 기능을 구현하거나 코드에서 예외를 잡을 수 있습니다(해당 부분의 구현은 내가 작성한 기능과 유사합니다. TypeError 와 구별할 수 있도록 나머지 코드에서 반복자 생성.


Luis Masuelli

다음 코드의 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

Nomad

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

 >>> 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

반복 불가능한 객체는 명백한 이유로 이것을 구현하지 않습니다. 그러나 그것을 구현하지 않는 사용자 정의 iterable이나 iter 가 처리할 수 있는 제너레이터 표현식은 catch하지 않습니다. 그러나 이것은 한 줄로 수행할 수 있으며 or 표현식 검사를 추가하면 이 문제가 해결됩니다. type(my_generator_expression) == generator 를 작성하면 NameError 가 발생합니다. 대신 답변을 참조하십시오.)

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

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

--- utdemir가 수락한 답변

(이렇게 하면 객체에서 len 을 호출할 수 있는지 확인하는 데 유용합니다.)


DarthCadeus

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

 >>> '__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

Jan Musil

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

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

lakam99

객체가 반복 가능한지 확인하는 많은 방법

 from collections.abc import Iterable myobject = 'Roster' if isinstance(myobject , Iterable): print(f"{myobject } is iterable") else: print(f"strong text{myobject } is not iterable")

Engr Tanveer sultan

출처 : http:www.stackoverflow.com/questions/1952464/in-python-how-do-i-determine-if-an-object-is-iterable

반응형