判斷
可通過模塊collections.abc和isinstance函數(shù)來驗證一個對象是否是可迭代(Iterable)畜份、迭代器(Iterable)以及生成器(Generator)。
可迭代對象
常見的對象比如string地粪、list聘芜、tuple、dict都是Iterable對象,他們都可以for循環(huán)遍歷每一個元素:
from collections.abc import Iterable, Iterator, Generator
obj_1 = 'abcde' # string
obj_2 = [1,2,3,4,5] # list
obj_3 = (5,4,3,2,1) #tuple
obj_4 = {'1':1, '2':2} #dict
obj_5 = 4 #int
print('string %s Iterable' % ('is' if isinstance(obj_1, Iterable) else 'is not'))
print('list %s Iterable' % ('is' if isinstance(obj_2, Iterable) else 'is not'))
print('tuple %s Iterable' % ('is' if isinstance(obj_3, Iterable) else 'is not'))
print('dict %s Iterable' % ('is' if isinstance(obj_4, Iterable) else 'is not'))
print('int %s Iterable' % ('is' if isinstance(obj_5, Iterable) else 'is not'))
輸出結(jié)果為:
string is Iterable
list is Iterable
tuple is Iterable
dict is Iterable
int is not Iterable
Iterable對象的本質(zhì)是該對象內(nèi)部實現(xiàn)了一個__iter__方法伤靠,也可使用dir函數(shù)通過判斷該對象是否有__iter__方法來判別是否為Iterable對象。使用for循環(huán)實際上干了兩件事啼染,首先調(diào)用__iter__返回一個對象宴合,該對象必須有__next__方法,然后再循環(huán)調(diào)用該對象的__next__方法不斷獲取下一個值迹鹅。
迭代器
同時實現(xiàn)了__iter__卦洽、__next__方法的對象為迭代器,若一個對象定義了__next__方法徒欣,則除了for循環(huán)外逐样,還可以將該對象作為next方法的輸入?yún)?shù)以獲取下一個迭代值。
下面的例子定義了一個可迭代對象NaturalNumberList打肝,他接受一個自然數(shù)脂新,然后存儲了到該自然數(shù)的所有自然數(shù)。
from collections.abc import Iterable, Iterator, Generator
class NaturalNumberList:
def __init__(self, num):
self.num = num
def __iter__(self):
return NaturalNumberIterator(self.num) # 返回一個跌代器
class NaturalNumberIterator:
def __init__(self, num):
self.num = num
self.currentValue = -1
def __iter__(self):
return self
def __next__(self):
if self.currentValue < self.num:
self.currentValue += 1
return self.currentValue # 每次調(diào)用返回該次循環(huán)的值
else:
raise StopIteration() # 循環(huán)結(jié)束
naturalNumberList = NaturalNumberList(5)
naturalNumberIterator = NaturalNumberIterator(5)
print('naturalNumberList %s Iterable' % ('is' if isinstance(naturalNumberList, Iterable) else 'is not'))
print('naturalNumberList %s Iterator' % ('is' if isinstance(naturalNumberList, Iterator) else 'is not'))
print('naturalNumberIterator %s Iterable' % ('is' if isinstance(naturalNumberIterator, Iterable) else 'is not'))
print('naturalNumberIterator %s Iterator' % ('is' if isinstance(naturalNumberIterator, Iterator) else 'is not'))
for item in naturalNumberList:
print(item)
輸出結(jié)果為:
naturalNumberList is Iterable
naturalNumberList is not Iterator
naturalNumberIterator is Iterable
naturalNumberIterator is Iterator
0
1
2
3
4
5
在上例中粗梭,NaturalNumberList是可迭代對象争便,但不是迭代器;naturalNumberIterator既是可迭代對象断医,又是迭代器滞乙。這個例子中奏纪,若NaturalNumberIterator類沒有__iter__方法,NaturalNumberList也能用for循環(huán)遍歷斩启,因為它有__next__方法序调,對于for循環(huán)已經(jīng)足夠了。
另外兔簇,有__next__方法而無__iter__方法的對象不能使用for循環(huán)遍歷发绢,但是可以用next方法遍歷,代碼如下:
it = iter([1, 2, 3, 4, 5])
while True:
try:
# 獲得下一個值:
x = next(it)
except StopIteration:
# 遇到StopIteration就退出循環(huán)
break
小結(jié)
- 有__iter__方法的對象都是可迭代對象垄琐,__iter__方法返回的對象必須含有__next__方法边酒。
- 僅有__next__方法的對象不能用for循環(huán)遍歷,而可以用next方法遍歷狸窘。
- 同時有__iter__和__next__方法的對象為迭代器墩朦。