web-dev-qa-db-ja.com

Pythonでは、オブジェクトが反復可能かどうかをどのように判断しますか?

isiterableのようなメソッドはありますか?私がこれまでに見つけた唯一の解決策は電話をかけることです

hasattr(myObj, '__iter__')

しかし、これがどれほどばかげた証拠なのか私にはわかりません。

908
willem
  1. __iter__をチェックすることはシーケンス型で機能しますが、それは失敗するでしょう。 Python 2の文字列。私は正しい答えも知りたいのですが、それまでは1つの可能性があります(これは文字列に対しても有効です)。

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

    iter組み込み関数は__iter__メソッドをチェックし、文字列の場合は__getitem__メソッドをチェックします。

  2. もう1つの一般的なPythonicのアプローチは、イテラブルを仮定し、それが与えられたオブジェクトでうまくいかない場合にはうまく失敗することです。 Pythonの用語集

    ある種の型オブジェクトとの明示的な関係ではなく、メソッドまたは属性シグネチャを調べることによってオブジェクトの型を決定するPythonicプログラミングスタイル( "duckのように見え、duckのようにおかしなことにa duck。 ")特定の型ではなくインターフェースを強調することで、うまく設計されたコードは多相代入を可能にすることによってその柔軟性を向上させます。ダックタイピングは、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__を通じて反復可能なクラスをチェックしません。

739
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)を呼び出すことです。

526
Georg Schölly

iter__iter__、および__getitem__の相互作用と、舞台裏で何が起こるのかをもう少し詳しく説明します。その知識を身に付けて、あなたは自分ができる最善の理由が何であるかを理解できるでしょう

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

最初に事実をリストしてから、pythonでforループを使用したときに何が起こるかを簡単に追いかけて、事実を説明するための議論を続けます。

事実

  1. 以下の条件の少なくとも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自体を発生させます。

  4. 最も一般的な意味では、iterによって返されたイテレータが正しいかどうかを調べる方法はありません。

  5. オブジェクトo__iter__を実装している場合、iter関数は__iter__によって返されるオブジェクトがイテレータであることを確認します。オブジェクトが__getitem__のみを実装しているかどうかの健全性チェックはありません。

  6. __iter__が勝ちます。オブジェクトo__iter____getitem__の両方を実装している場合、iter(o)__iter__を呼び出します。

  7. 自分のオブジェクトを反復可能にしたい場合は、常に__iter__メソッドを実装してください。

forループ

従うためには、Pythonでforループを使用したときに何が起こるかを理解する必要があります。ご存知の場合は、次のセクションに進んでください。

反復可能オブジェクトoに対してfor item in oを使用すると、Pythonはiter(o)を呼び出し、戻り値としてイテレータオブジェクトを期待します。イテレータは__next__(またはPython 2ではnext)メソッドと__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>

ただし、b__iter__属性を持たず、IterableまたはSequenceのインスタンスとは見なされないことに注意することが重要です。

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

これが、 Fluent Python Luciano Ramalhoがiterを呼び出すことと、オブジェクトが反復可能かどうかをチェックする最も正確な方法として潜在的なTypeErrorを処理することを推奨する理由です。本から直接引用する:

Python 3.4以降、オブジェクトxが反復可能かどうかを調べる最も正確な方法は、iter(x)を呼び出し、TypeError例外が処理されない場合はそれを処理することです。 isinstance(x, abc.Iterable)は従来の__getitem__メソッドも考慮しますが、Iterable ABCは考慮しないため、これはiter(x)を使用するよりも正確です。

要点3:__getitem__のみを提供し、__iter__を提供しないオブジェクトを反復処理する

BasicIterableのインスタンスを繰り返し処理すると、期待どおりに機能します。Pythonは、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を発生させ、item == 3のために発生するIndexErrorは内部的に処理されることに注意してください。これが、BasicIterableループを使用してforをループ処理することが期待どおりに機能する理由です。

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

iterによって返されたイテレータがインデックスによって項目にアクセスしようとする方法の概念を後押しするための別の例です。 WrappedDictdictから継承しません。つまり、インスタンスは__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__を呼び出すときにイテレータをチェックします

オブジェクトoに対してiter(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__への最初の呼び出しでExceptionがスローされます。

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

あなたのカスタムイテラブルが__iter__を実装する理由は以下の通りです:

  1. __iter__を実装すると、インスタンスはイテラブルと見なされ、isinstance(o, collections.Iterable)Trueを返します。
  2. __iter__によって返されたオブジェクトがイテレータではない場合、iterは直ちに失敗し、TypeErrorを送出します。
  3. __getitem__の特別な取り扱いは、後方互換性のために存在します。 Fluent Pythonからもう一度引用します。

これが、どんなPythonシーケンスでも反復可能な理由です。それらはすべて__getitem__を実装しています。実際、標準のシーケンスも__iter__を実装しており、__getitem__の特別な処理は下位互換性の理由から存在し、将来なくなるかもしれません(これを書いているので非推奨ではありませんが)。

85
timgeb

これだけでは十分ではありません。__iter__によって返されるオブジェクトは、反復プロトコル(つまりnextメソッド)を実装する必要があります。 ドキュメント の関連セクションを参照してください。

Pythonでは、「チェック」ではなく「試してみる」ことをお勧めします。

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

確認するためにチェックを実行しない あなたのアヒルが本当にアヒルなら それが反復可能かどうかを確かめるために、それがそうであるかのようにそれを扱い、そうでないなら不平を言う。

20
badp

Python <= 2.5では、あなたはできませんし、そうすべきではありません - イテレータブルは「非公式な」インターフェースでした。

しかし、Python 2.6および3.0以降では、collectionsモジュールで利用可能ないくつかの組み込みABCとともに、新しいABC(abstract base class)インフラストラクチャを利用できます。

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としてcan登録すると、実行時に例外が発生します。それゆえ、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 __== "__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は自動的にそのクラスのオブジェクトを反復可能であると認識します。

ですから、もしあなたがイテラブルを期待しているのなら、それをイテレートして忘れてください。一方、入力タイプに応じてさまざまなことをする必要がある場合は、ABCインフラストラクチャが非常に便利です。

19
Alan Franzoni

私がこれまでに見つけた最高のソリューション:

hasattr(obj, '__contains__')

基本的に、オブジェクトがin演算子を実装しているかどうかを確認します。

利点(他のソリューションには3つすべてがありません):

  • これは式です(try ... exceptバリアントではなくlambdaとして機能します)
  • strings__iter__とは対照的に)を含むすべての反復可能オブジェクトによって実装される(されるべき)
  • Python> = 2.5で動作します

ノート:

  • 「許可ではなく許しを求める」というPython哲学は、たとえばリストには反復可能要素と反復不可能要素の両方があり、各要素をそのタイプに応じて異なる方法で処理する必要があります(試行時に反復可能要素を処理し、 would workお尻がlookくて誤解を招く恐れがあります)
  • 反復可能かどうかを確認するためにオブジェクト(たとえば[obj for in obj])を実際に反復しようとするこの問題の解決策は、大きな反復可能オブジェクトに対して著しいパフォーマンスの低下を引き起こす可能性があります(特に反復可能オブジェクトの最初のいくつかの要素だけが必要な場合、例)避けるべき
18
Vlad

私はいい解決策を見つけました ここ

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

あなたはこれを試すことができます:

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

それを繰り返すジェネレータを作ることができれば(しかし、ジェネレータを使わないのでスペースをとらない)、それは繰り返し可能です。 「当たり前」のようなもののようです。最初に変数が反復可能かどうかを判断する必要があるのはなぜですか。

12
Chris Lutz

Python 2用語集 によると、イテラブルは

すべてのシーケンス型(liststrTupleなど)、およびdictおよびfileなどの一部の非シーケンス型、ならびに__iter__()または__getitem__()メソッドで定義した任意のクラスのオブジェクトイテラブルは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__")によってイテラブルをテストすることができます。 strsは__iter__メソッドを持っていないので(少なくともPython 2では、Python 3ではそうではありません)、generatorオブジェクトは__getitem__メソッドを持っていないので、両方をチェックする必要があります。

10
Anaphory

Python 3.5 以降、型に関することには標準ライブラリの typing モジュールを使用できます。

from typing import Iterable

...

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

pandas には以下のような組み込み関数があります。

from pandas.util.testing import isiterable
5
Sören

私はスクリプト内でiterable関数を定義するのが便利だと思うことがよくあります。 (現在はAlfeが提案した単純化を取り入れています):

import collections

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

そのため、読みやすい形式でオブジェクトが反復可能かどうかをテストできます。

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

callable関数と同じように

編集:あなたが厄介なインストールされている場合は、単に行うことができます:numpy import iterableから、これは単にのようなものです

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

おかしなことがない場合は、このコードまたは上記のコードを単純に実装できます。

5
fmonegaglia

pythonがcallable(obj) -> boolを持っているがiterable(obj) -> boolを持たない理由についてはいつも私を避けていました...
遅くてもhasattr(obj,'__call__')を実行する方が簡単です。

他のほぼすべての答えがtry/except TypeErrorを使用することを推奨しているので、例外のテストは一般にあらゆる言語で悪い習慣と見なされているので、ここではiterable(obj) -> bool頻繁に使用する:

python 2のために、パフォーマンスを向上させるためにラムダを使用します...
(python 3では、関数の定義に何を使用してもかまいません。deflambdaとほぼ同じ速度です)

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

この関数は、__iter__をテストしないため、__getitem__を含むオブジェクトに対してより高速に実行されることに注意してください。

ほとんどの反復可能オブジェクトは__iter__に依存する必要があります。特殊ケースのオブジェクトは__getitem__にフォールバックしますが、オブジェクトを反復可能にするにはいずれかが必要です。
(これは標準であるため、Cオブジェクトにも影響します)

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

注:is_iterable()はbytes型とbytearray型の文字列に対してyesと答えます。

  • Python 3のbytesオブジェクトは反復可能ですTrue == is_iterable(b"string") == is_iterable("string".encode('utf-8')) Python 2にはそのような型はありません。
  • Python 2と3のbytearrayオブジェクトは反復可能ですTrue == is_iterable(bytearray(b"abc"))

O.P. hasattr(x, '__iter__')アプローチは、Python 3では文字列に対してyesを、Python 2ではnoとします(''b''u''のいずれを問わず)。 @LuisMasuelliさん、バグのある__iter__についてもお知らせします。

3
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. __call__が自分のオブジェクトに定義されていない場合でも、callablename__をレイズするためにアヒルの型付けに頼ることができるのであれば、AttributeErrorname__はどのようにチェックとして存在するのでしょうか。

    答えはわかりませんが、私(および他のユーザー)が提供した関数を実装するか、コード内で例外をキャッチすることができます(その部分の実装は、私が書いた関数のようになります。残りのコードからイテレータを作成するので、例外を捕捉して別のTypeErrorname__と区別できます。

2
Luis Masuelli

__iter__属性をチェックする代わりに、__len__属性をチェックすることができます。これは文字列を含むすべてのpython組み込みイテラブルによって実装されています。

>>> 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) == generatorを書くとNameErrorがスローされることに注意してください。代わりに this answerを参照してください。)

型からGeneratorTypeを使用できます。

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

--- utdemirによる回答が承認されました

(これにより、オブジェクトでlenを呼び出せるかどうかを確認するのに役立ちます。)

1
DarthCadeus

次のコードのisiterable funcは、objectが反復可能であれば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
1
Nomad

ちょっとパーティーに遅れましたが、私はこの質問を自問し、これを見て、答えを考えました。誰かがすでにこれを投稿しているかどうかはわかりません。しかし、本質的に、すべての反復可能な型の辞書に「getitem」が含まれていることに気付きました。これは、試行することなくオブジェクトが反復可能かどうかを確認する方法です。 (意図したパン)

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

実際はそうではありません "正しい" しかし文字列、タプル、フロートなどのような最も一般的な型の簡単なチェックとして役立つことができます...

>>> '__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
0
Jan Musil