引子
在django中執(zhí)行查詢如
queryset = User.objects.all()
查詢出來的query是惰性,只有當你調用的時候才會真正去執(zhí)行sql
比如說print queryset
時,才去執(zhí)行
那么問題來了?他是怎么打印的?
iter的理解
當print的時候,調用下面:
repr(list(self))
顯然list()對象實例實例化的時候,需要一個可迭代的(iterable)對象.
什么可迭代的對象?
可迭代(iterable)
-1 支持迭代協(xié)議的(the iteration protocol )
有__iter__()
返回一個具有next()方法的對像.不停調用next(),結束拋出StopItertion異常的
-2 支持序列協(xié)議的(the sequence protocol)
有__getitem__(self,item)
方法且item從0開始的整數(shù)
class Iter(object):
def __init__(self):
self.ini = 10
# def __iter__(self):
# print 111
# return self
#
# def next(self):
# print 222
# if self.ini < 3:
# raise StopIteration
# self.ini -= 2
# return self.ini
def __len__(self):
print 333
def __getitem__(self, item):
self.ini -= 1
if self.ini < 0:
raise StopIteration
return item
a = list(Iter())
for i in a:
print i,
輸出
333
0 1 2 3 4 5 6 7 8 9
注意:
1
__iter__()
優(yōu)先級別高于__getitem__
,兩者都在的時候,前者起作用2 調用順序
情況1
__iter__-->__len__-->next
情況2
__len_--> __getitem__
此外值得注意的一點,迭代器對象只能用一次
a = list(Iter())
for i in a:
print i,
print "\n"
for i in a:
print i,
print "\n"
b = iter(Iter())
for i in b:
print i,
print "\n"
for i in b:
print 1,
print "\n"
#輸出
333
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9