日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python判断一个对象是否可迭代_python - 在Python中,如何确定对象是否可迭代? - includeStdio...

發(fā)布時(shí)間:2023/12/15 python 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python判断一个对象是否可迭代_python - 在Python中,如何确定对象是否可迭代? - includeStdio... 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

有沒有像isiterable?我目前找到的唯一解決方案就是打電話

hasattr(myObj, '__iter__')

但我不確定這是多么的愚蠢。

檢查__iter__序列類型的工作,但是它會(huì)在例如Python 2中的字符串上失敗。我想知道正確的答案,在那之前,這里有一種可能性(也可以在字符串上工作):

try:some_object_iterator=iter(some_object)

except TypeError aste:

printsome_object, 'is not iterable'

該方法的iter內(nèi)置檢查__iter__或字符串__getitem__方法的內(nèi)置檢查。

另一種普遍的pythonic方法是假設(shè)一個(gè)可迭代的,然后優(yōu)雅地失敗,如果它不能在給定的對(duì)象上工作。Python詞匯表:

Pythonic編程風(fēng)格通過檢查它的方法或?qū)傩院灻皇峭ㄟ^與某些類型對(duì)象的顯式關(guān)系來確定對(duì)象的類型(“如果它看起來像鴨子和鴨子一樣,它肯定是鴨子。”)通過強(qiáng)調(diào)接口而不是特定類型,精心設(shè)計(jì)的代碼通過允許多態(tài)替代來提高其靈活性。鴨子鍵入避免使用type()或isinstance()進(jìn)行測試。相反,它通常采用EAFP(容易提出寬恕而不是權(quán)限)編程風(fēng)格。

try:_= (eforeinmy_object)

except TypeError:

printmy_object, 'is not iterable'

該collections模塊提供了一些抽象基類,它允許詢問類或?qū)嵗欠裉峁┨囟üδ?#xff0c;例如:

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)檢測到已注冊(cè)為Iterable或具有__iter__()方法的類,但未檢測到與該__getitem__()?方法重復(fù)的類。確定對(duì)象是否可迭代的唯一可靠方法是調(diào)用iter(obj)。

我想闡明的相互多一點(diǎn)光iter,__iter__并__getitem__會(huì)發(fā)生什么窗簾后面。有了這些知識(shí),你就能明白為什么你能做的最好

try:iter(maybe_iterable)

print('iteration will probably work')

except TypeError:

print('not iterable')

我將首先列出事實(shí),然后快速提醒您for在Python中使用循環(huán)時(shí)會(huì)發(fā)生什么,然后進(jìn)行討論以說明事實(shí)。

事實(shí)

如果滿足以下至少一個(gè)條件o,則可以調(diào)用任何對(duì)象的迭代器iter(o):

a)返回一個(gè)迭代器對(duì)象o的__iter__方法。迭代器是帶有__iter__和__next__(Python 2?:)方法的任何對(duì)象next。

b)o有一個(gè)__getitem__方法。

檢查Iterableor?的實(shí)例Sequence或檢查屬性__iter__是不夠的。

如果一個(gè)對(duì)象o只實(shí)現(xiàn)__getitem__,但不是__iter__,iter(o)將構(gòu)建嘗試從取物品的迭代器o由整數(shù)索引,開始于索引0。迭代器將捕獲任何IndexError被提升(但沒有其他錯(cuò)誤),然后使StopIteration本身。

從最一般意義上說,沒有辦法檢查返回的迭代器是否iter理智,而不是嘗試它。

如果一個(gè)對(duì)象o實(shí)現(xiàn)__iter__,該iter函數(shù)將確保返回的對(duì)象__iter__是一個(gè)迭代器。如果一個(gè)對(duì)象只實(shí)現(xiàn),沒有理智檢查__getitem__。

__iter__勝。如果一個(gè)對(duì)象o同時(shí)實(shí)現(xiàn)了__iter__和__getitem__,iter(o)將調(diào)用__iter__。

如果您想讓自己的對(duì)象可迭代,請(qǐng)始終實(shí)施該__iter__方法。

for?循環(huán)

為了跟隨,您需要了解for在Python中使用循環(huán)時(shí)會(huì)發(fā)生什么。如果您已經(jīng)知道,請(qǐng)隨意跳到下一節(jié)。

當(dāng)你使用for item in o某個(gè)可迭代對(duì)象時(shí)o,Python會(huì)調(diào)用iter(o)并期待一個(gè)迭代器對(duì)象作為返回值。迭代器是實(shí)現(xiàn)__next__(或next在Python 2中)方法和__iter__方法的任何對(duì)象。

按照慣例,__iter__迭代器的方法應(yīng)該返回對(duì)象本身(即return self)。Python然后調(diào)用next迭代器直到StopIteration被引發(fā)。所有這些都隱含地發(fā)生,但下面的演示使其可見:

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點(diǎn)和第2點(diǎn):獲得迭代器和不可靠的檢查

考慮以下課程:

class BasicIterable(object):

def__getitem__(self,item):

ifitem== 3:

raise IndexError

returnitem

調(diào)用iter一個(gè)實(shí)例BasicIterable將會(huì)返回一個(gè)沒有任何問題的迭代器,因?yàn)锽asicIterableimplements?__getitem__。

>>>b= BasicIterable()

>>>iter(b)

但是,重要的是要注意,b它沒有__iter__屬性,并且不被視為Iterable或的一個(gè)實(shí)例Sequence:

>>> fromcollectionsimport Iterable, Sequence

>>>hasattr(b, '__iter__')

False

>>>isinstance(b, Iterable)

False

>>>isinstance(b, Sequence)

False

這就是為什么Luciano Ramalho的Fluent Python推薦調(diào)用iter和處理潛在性,TypeError作為檢查對(duì)象是否可迭代的最準(zhǔn)確的方法。直接從書中引用:

從Python 3.4開始,檢查對(duì)象x是否可迭代的最準(zhǔn)確的方法是調(diào)用iter(x)并處理TypeError異常(如果不是)。這比使用更準(zhǔn)確isinstance(x, abc.Iterable),因?yàn)樗黫ter(x)也考慮了傳統(tǒng)__getitem__方法,而IterableABC則沒有。

在第3點(diǎn):迭代只提供的對(duì)象__getitem__,但不是__iter__

BasicIterable按照期望對(duì)工作實(shí)例進(jìn)行迭代:Python構(gòu)造一個(gè)迭代器,它嘗試通過索引從零開始提取項(xiàng)目,直到IndexError引發(fā)為止。演示對(duì)象的__getitem__方法只是返回由返回的迭代器item提供的參數(shù)。__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時(shí),它不能返回的下一個(gè)項(xiàng)目,而且IndexError它提高了item == 3內(nèi)部處理。這就是為什么在循環(huán)BasicIterable使用for循環(huán)按預(yù)期工作:

>>> forxinb:

... print(x)

...

0

1

2

下面是另一個(gè)例子,以便iter通過索引來訪問迭代器返回的概念。WrappedDict不從繼承dict,這意味著實(shí)例不會(huì)有__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

請(qǐng)注意,調(diào)用__getitem__是委托給dict.__getitem__的,方括號(hào)表示法只是簡寫。

>>>w= WrappedDict({-1: 'not printed',

... 0: 'hi', 1: 'StackOverflow', 2: '!',

... 4: 'not printed',

... 'x': 'not printed'})

>>> forxinw:

... print(x)

...hiStackOverflow

!

在第4點(diǎn)和第5點(diǎn):iter它調(diào)用時(shí)檢查迭代器__iter__:

何時(shí)iter(o)調(diào)用對(duì)象o,iter將確保返回值(__iter__如果方法存在)是迭代器。這意味著返回的對(duì)象必須實(shí)現(xiàn)__next__(或next在Python 2中)和__iter__。iter不能對(duì)僅提供的對(duì)象執(zhí)行任何理智檢查__getitem__,因?yàn)樗鼰o法檢查對(duì)象的項(xiàng)是否可以通過整數(shù)索引訪問。

class FailIterIterable(object):

def__iter__(self):

returnobject() # not an iterator

class FailGetitemIterable(object):

def__getitem__(self,item):

raise Exception

請(qǐng)注意,從FailIterIterable實(shí)例構(gòu)造一個(gè)迭代器會(huì)立即失敗,同時(shí)從FailGetItemIterable成功構(gòu)建一個(gè)迭代器,但會(huì)在第一次調(diào)用時(shí)拋出一個(gè)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點(diǎn):__iter__勝利

這一個(gè)很簡單。如果一個(gè)對(duì)象實(shí)現(xiàn)__iter__和__getitem__,iter將調(diào)用__iter__。考慮以下課程

class IterWinsDemo(object):

def__iter__(self):

returniter(['__iter__', 'wins'])

def__getitem__(self,item):

return ['__getitem__', 'wins'][item]

以及循環(huán)實(shí)例時(shí)的輸出:

>>>iwd= IterWinsDemo()

>>> forxiniwd:

... print(x)

...__iter__

wins

在第7點(diǎn):你的迭代類應(yīng)該實(shí)現(xiàn)?__iter__

你可能會(huì)問自己,為什么大多數(shù)內(nèi)建序列像是在足夠的時(shí)候list實(shí)現(xiàn)一種__iter__方法__getitem__。

class WrappedList(object): # note: no inheritance from list!

def__init__(self,lst):self._list=lstdef__getitem__(self,item):

returnself._list[item]

畢竟,在重復(fù)上面的類,它代表調(diào)用的情況下__getitem__,以list.__getitem__(使用方括號(hào)),將正常工作:

>>>wl= WrappedList(['A', 'B', 'C'])

>>> forxinwl:

... print(x)

...A

B

C

你的自定義迭代應(yīng)該實(shí)現(xiàn)的原因__iter__如下:

如果你實(shí)現(xiàn)了__iter__,實(shí)例將被認(rèn)為是可迭代的,并且isinstance(o, collections.Iterable)會(huì)返回True。

如果返回的對(duì)象__iter__不是迭代器,iter將立即失敗并引發(fā)一個(gè)TypeError。

__getitem__出于向后兼容性的原因存在特殊處理。從Fluent Python再次引用:

這就是為什么任何Python序列都是可迭代的:它們都實(shí)現(xiàn)了__getitem__。實(shí)際上,標(biāo)準(zhǔn)序列也可以實(shí)現(xiàn)__iter__,而且你也應(yīng)該這樣做,因?yàn)開_getitem__為了向后兼容的原因存在特殊的處理,并且可能在將來消失(盡管在我寫這篇文章時(shí)不會(huì)棄用)。

總結(jié)

以上是生活随笔為你收集整理的python判断一个对象是否可迭代_python - 在Python中,如何确定对象是否可迭代? - includeStdio...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。