2010-06-11 71 views

回答

37

在Python 2.6或更高,所設計的,在成語對於這種行爲的檢查是一種「成員資格檢查」與抽象基類的collections模塊的標準庫中:

>>> import collections 
>>> isinstance('ciao', collections.Iterable) 
True 
>>> isinstance(23, collections.Iterable) 
False 
>>> isinstance(xrange(23), collections.Iterable) 
True 

事實上,這種檢查是首要的設計原因,新的抽象基類(第二重要的是在一些提供「混入功能」案件,這就是爲什麼他們是ABC rath呃不只是接口 - 但這不適用於collections.Iterable,它存在嚴格允許與isinstanceissubclass)這樣的檢查。 ABCs允許那些實際上並不從它們繼承的類被「註冊」爲子類,因此這些類可以是ABC的「子類」,用於這種檢查;並且他們可以在內部執行特殊方法所需的全部檢查(本例中爲__iter__),因此您不必這樣做。

如果你堅持與Python的舊版本,「這是更好地請求原諒比許可」:

def isiterable(x): 
    try: iter(x) 
    except TypeError: return False 
    else: return True 

但是這沒有那麼快,簡潔的新方法。

請注意,對於這種特殊情況,您經常需要特殊字符串(這是可迭代的,但大多數應用程序上下文無論如何都要將其視爲「標量」)。不管你的方法是使用檢查iterableness,如果你需要這種特殊的外殼只是在前面加上一個檢查isinstance(x, basestring) - 例如:

def reallyiterable(x): 
    return not isinstance(x, basestring) and isinstance(x, collections.Iterable) 

編輯:如在評論中指出,問題集中在是否一個對象是一個****,而不是它是否可以***(所有迭代器都可迭代,但反之亦然 - 並非所有迭代器都是迭代器)。 isinstance(x, collections.Iterator)是專門檢查該情況的完全類似方法。

+9

這些問題詢問對象是否是迭代器,而不是如果它是可迭代的。所以你應該使用collections.Iterator而不是collections.Iterable – 2010-06-11 17:04:40

+0

@Dave,對,讓我編輯澄清。 – 2010-06-11 18:04:33

9

如果對象實現迭代器協議,則該對象是可迭代的。
你可以檢查__iter__()方法存在有:

hasattr(object,'__iter__') 

在Python 2.x的這種方法忽略海峽對象和其他內置序列類型,如統一,x範圍,緩衝區。它的工作原理在Python 3

另一種方式是與國際熱核實驗堆的方法來測試它:

try: 
    iter(object) 
except TypeError: 
    #not iterable 
+1

創建迭代器可能是昂貴的,而檢查屬性的存在總是*快*。 – 2012-09-29 16:35:58

4

要成爲一個迭代的對象必須通過三個測試:

  • obj具有(在Python 3或__next__)的__iter__方法
  • obj具有next方法
  • obj.__iter__()返回obj

所以,一個自己的測試會看起來像:

def is_iterator(obj): 
    if (
      hasattr(obj, '__iter__') and 
      hasattr(obj, 'next') and  # or __next__ in Python 3 
      callable(obj.__iter__) and 
      obj.__iter__() is obj 
     ): 
     return True 
    else: 
     return False 
+0

會調用'obj .__ iter __()'冒着改變某些東西的風險嗎? – 2017-09-25 18:38:42

+0

@ BobStein-VisiBone:只有當對象有問題時。 – 2018-02-06 16:49:34

相關問題