python判断一个对象是否可迭代_python - 在Python中,如何确定对象是否可迭代? - includeStdio...
有沒有像isiterable?我目前找到的唯一解決方案就是打電話
hasattr(myObj, '__iter__')
但我不確定這是多么的愚蠢。
檢查__iter__序列類型的工作,但是它會在例如Python 2中的字符串上失敗。我想知道正確的答案,在那之前,這里有一種可能性(也可以在字符串上工作):
try:some_object_iterator=iter(some_object)
except TypeError aste:
printsome_object, 'is not iterable'
該方法的iter內置檢查__iter__或字符串__getitem__方法的內置檢查。
另一種普遍的pythonic方法是假設一個可迭代的,然后優雅地失敗,如果它不能在給定的對象上工作。Python詞匯表:
Pythonic編程風格通過檢查它的方法或屬性簽名而不是通過與某些類型對象的顯式關系來確定對象的類型(“如果它看起來像鴨子和鴨子一樣,它肯定是鴨子。”)通過強調接口而不是特定類型,精心設計的代碼通過允許多態替代來提高其靈活性。鴨子鍵入避免使用type()或isinstance()進行測試。相反,它通常采用EAFP(容易提出寬恕而不是權限)編程風格。
…
try:_= (eforeinmy_object)
except TypeError:
printmy_object, 'is not iterable'
該collections模塊提供了一些抽象基類,它允許詢問類或實例是否提供特定功能,例如:
importcollectionsifisinstance(e,collections.Iterable):
# e is iterable
但是,這并不檢查可迭代的類__getitem__。
鴨子打字
try:iterator=iter(theElement)
except TypeError:
# not iterable
else:
# iterable
# for obj in iterator:
# pass
類型檢查
使用抽象基類。他們至少需要Python 2.6,并且僅適用于新式類。
importcollectionsifisinstance(theElement,collections.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在Python中使用循環時會發生什么,然后進行討論以說明事實。
事實
如果滿足以下至少一個條件o,則可以調用任何對象的迭代器iter(o):
a)返回一個迭代器對象o的__iter__方法。迭代器是帶有__iter__和__next__(Python 2?:)方法的任何對象next。
b)o有一個__getitem__方法。
檢查Iterableor?的實例Sequence或檢查屬性__iter__是不夠的。
如果一個對象o只實現__getitem__,但不是__iter__,iter(o)將構建嘗試從取物品的迭代器o由整數索引,開始于索引0。迭代器將捕獲任何IndexError被提升(但沒有其他錯誤),然后使StopIteration本身。
從最一般意義上說,沒有辦法檢查返回的迭代器是否iter理智,而不是嘗試它。
如果一個對象o實現__iter__,該iter函數將確保返回的對象__iter__是一個迭代器。如果一個對象只實現,沒有理智檢查__getitem__。
__iter__勝。如果一個對象o同時實現了__iter__和__getitem__,iter(o)將調用__iter__。
如果您想讓自己的對象可迭代,請始終實施該__iter__方法。
for?循環
為了跟隨,您需要了解for在Python中使用循環時會發生什么。如果您已經知道,請隨意跳到下一節。
當你使用for item in o某個可迭代對象時o,Python會調用iter(o)并期待一個迭代器對象作為返回值。迭代器是實現__next__(或next在Python 2中)方法和__iter__方法的任何對象。
按照慣例,__iter__迭代器的方法應該返回對象本身(即return self)。Python然后調用next迭代器直到StopIteration被引發。所有這些都隱含地發生,但下面的演示使其可見:
importrandomclass DemoIterable(object):
def__iter__(self):
print('__iter__ called')
return DemoIterator()
class DemoIterator(object):
def__iter__(self):
returnselfdef__next__(self):
print('__next__ called')r=random.randint(1, 10)
ifr== 5:
print('raising StopIteration')
raise StopIteration
returnr
迭代遍歷DemoIterable:
>>>di= DemoIterable()
>>> forxindi:
... print(x)
...__iter__ called
__next__ called9__next__ called8__next__ called10__next__ called3__next__ called10__next__ called
raisingStopIteration
討論和插圖
在第1點和第2點:獲得迭代器和不可靠的檢查
考慮以下課程:
class BasicIterable(object):
def__getitem__(self,item):
ifitem== 3:
raise IndexError
returnitem
調用iter一個實例BasicIterable將會返回一個沒有任何問題的迭代器,因為BasicIterableimplements?__getitem__。
>>>b= BasicIterable()
>>>iter(b)
但是,重要的是要注意,b它沒有__iter__屬性,并且不被視為Iterable或的一個實例Sequence:
>>> fromcollectionsimport 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異常(如果不是)。這比使用更準確isinstance(x, abc.Iterable),因為它iter(x)也考慮了傳統__getitem__方法,而IterableABC則沒有。
在第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 "",line1, in
StopIteration
需要注意的是,迭代器拋出StopIteration時,它不能返回的下一個項目,而且IndexError它提高了item == 3內部處理。這就是為什么在循環BasicIterable使用for循環按預期工作:
>>> forxinb:
... print(x)
...
0
1
2
下面是另一個例子,以便iter通過索引來訪問迭代器返回的概念。WrappedDict不從繼承dict,這意味著實例不會有__iter__方法。
class WrappedDict(object): # note: no inheritance from dict!
def__init__(self,dic):self._dict=dicdef__getitem__(self,item):
try:
returnself._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'})
>>> forxinw:
... print(x)
...hiStackOverflow
!
在第4點和第5點:iter它調用時檢查迭代器__iter__:
何時iter(o)調用對象o,iter將確保返回值(__iter__如果方法存在)是迭代器。這意味著返回的對象必須實現__next__(或next在Python 2中)和__iter__。iter不能對僅提供的對象執行任何理智檢查__getitem__,因為它無法檢查對象的項是否可以通過整數索引訪問。
class FailIterIterable(object):
def__iter__(self):
returnobject() # not an iterator
class FailGetitemIterable(object):
def__getitem__(self,item):
raise Exception
請注意,從FailIterIterable實例構造一個迭代器會立即失敗,同時從FailGetItemIterable成功構建一個迭代器,但會在第一次調用時拋出一個Exception?__next__。
>>>fii= FailIterIterable()
>>>iter(fii)
Traceback (most recent call last):
File "",line1, in
TypeError:iter()returned non-iterator of type'object'
>>>
>>>fgi= FailGetitemIterable()
>>>it=iter(fgi)
>>>next(it)
Traceback (most recent call last):
File "",line1, in
File "/path/iterdemo.py",line42, in__getitem__raise Exception
Exception
在第6點:__iter__勝利
這一個很簡單。如果一個對象實現__iter__和__getitem__,iter將調用__iter__。考慮以下課程
class IterWinsDemo(object):
def__iter__(self):
returniter(['__iter__', 'wins'])
def__getitem__(self,item):
return ['__getitem__', 'wins'][item]
以及循環實例時的輸出:
>>>iwd= IterWinsDemo()
>>> forxiniwd:
... print(x)
...__iter__
wins
在第7點:你的迭代類應該實現?__iter__
你可能會問自己,為什么大多數內建序列像是在足夠的時候list實現一種__iter__方法__getitem__。
class WrappedList(object): # note: no inheritance from list!
def__init__(self,lst):self._list=lstdef__getitem__(self,item):
returnself._list[item]
畢竟,在重復上面的類,它代表調用的情況下__getitem__,以list.__getitem__(使用方括號),將正常工作:
>>>wl= WrappedList(['A', 'B', 'C'])
>>> forxinwl:
... print(x)
...A
B
C
你的自定義迭代應該實現的原因__iter__如下:
如果你實現了__iter__,實例將被認為是可迭代的,并且isinstance(o, collections.Iterable)會返回True。
如果返回的對象__iter__不是迭代器,iter將立即失敗并引發一個TypeError。
__getitem__出于向后兼容性的原因存在特殊處理。從Fluent Python再次引用:
這就是為什么任何Python序列都是可迭代的:它們都實現了__getitem__。實際上,標準序列也可以實現__iter__,而且你也應該這樣做,因為__getitem__為了向后兼容的原因存在特殊的處理,并且可能在將來消失(盡管在我寫這篇文章時不會棄用)。
總結
以上是生活随笔為你收集整理的python判断一个对象是否可迭代_python - 在Python中,如何确定对象是否可迭代? - includeStdio...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android手机上使用Socks5全局
- 下一篇: 阿里短信单发,批量发送_如何用阿里小号发