迭代器:初探
在之前介绍过,for循环可以用于Python中任何序列类型,包括列表、元组以及字符串,如下所示:
>>> for x in [1,2,3,4]:print(x**2,end=" ")
1 4 9 16
>>> for x in (1,2,3,4):print(x**3,end = ' ')
1 8 27 64
>>> for x in 'spam' :print(x*2,end=' ')
ss pp aa mm
实际上,for循环甚至比这更为通用:可用于任何可迭代的对象。
实际上,对Python中所有会从左至右扫描对象的迭代工具而言都是如此,这些迭代工具包括了for循环、列表解析、in成员关系测试以及map内置函数等
'可迭代对象'在语言设计中很普遍,基本上,这就是序列观念的通用化:如果对象是实际保存的序列,或者可以在迭代工具环境中一次产生一个结果的对象,就看做时可迭代的。
===============================================================================
文件迭代器
已打开的文件对象中有个方法名为readline,可以一次从一个文件中读取一行文本,每次调用readline方法时,就会前进到下一行,到达文件末尾时,就会返回空字符串:
>>> f = open(r'F:\002calc.py')
>>> f.readline()
'temp = input("Please input a number:\\n")\n'
>>> f.readline()
'num = int(temp)\n'
>>> f.readline()
'if 1<=num<=100:\n'
>>> f.readline()
' print("your sister is beautiful!")\n'
>>> f.readline()
'else:\n'
>>> f.readline()
' print("your oldfather is ugly!")\n'
>>> f.readline()
''
>>> f.readline()
''
现在,文件对象中也有一个方法名,为__next__,差不多有同样的效果,每次调用时,就会返回文件中的下一行。
值得注意的区别是,到达文件末尾时,__next__方法会引发内置的StopIteration异常,而不是返回空字符串。
>>> f = open(r'F:\002calc.py')
>>> f.__next__()
'temp = input("Please input a number:\\n")\n'
>>> f.__next__()
'num = int(temp)\n'
>>> f.__next__()
'if 1<=num<=100:\n'
>>> f.__next__()
' print("your sister is beautiful!")\n'
>>> f.__next__()
'else:\n'
>>> f.__next__()
' print("your oldfather is ugly!")\n'
>>> f.__next__()
Traceback (most recent call last):
File "<pyshell#22>", line 1, in <module>
f.__next__()
StopIteration
这个接口就是Python中所谓的
迭代协议:
有__next__方法的对象会前进到下一个结果,而在一系列结果的末尾时,则会引发StopIteration。
在Python中,任何这类对象都认为是可迭代的。任何这类对象也能以for循环或其他迭代工具遍历,因为所有迭代工具内部工作起来都是在每次迭代中调用__next__,并且捕捉StopIteration异常来确定何时离开。
这种魔法的效果就是,逐行读取文本文件的最佳方式就是根本不要去读取;其替代的办法就是,让for循环在每轮自动调用next从而前进到下一行:
>>> for line in open(r'F:\002calc.py'):
print(line.upper(),end='')
TEMP = INPUT("PLEASE INPUT A NUMBER:\N")
NUM = INT(TEMP)
IF 1<=NUM<=100:
PRINT("YOUR SISTER IS BEAUTIFUL!")
ELSE:
PRINT("YOUR OLDFATHER IS UGLY!")
注意:这里的print使用end=' '来抑制添加一个'\n',因为行字符串已经有了一个。
上例是读取文本文件的最佳方式,原因有三点:这是最简单的写法,运行最快,并且从内存使用情况来看也是最好的。
相同效果的原始方式,是以for循环调用文件的readlines方法,将文件内容加载到内存,做成行字符串列表。
>>> open(r'F:\002calc.py').readlines()
['temp = input("Please input a number:\\n")\n', 'num = int(temp)\n', 'if
1<=num<=100:\n', ' print("your sister is beautiful!")\n', 'else:\n', '
print("your oldfather is ugly!")\n']
>>> for line in open(r'F:\002calc.py').readlines():
print(line.upper(),end='')
TEMP = INPUT("PLEASE INPUT A NUMBER:\N")
NUM = INT(TEMP)
IF 1<=NUM<=100:
PRINT("YOUR SISTER IS BEAUTIFUL!")
ELSE:
PRINT("YOUR OLDFATHER IS UGLY!")
这种方法比较耗内存。
===============================================================================
手动迭代:iter和next
为了支持手动迭代代码(用于较少的录入),Python3.0还提供了一个内置函数next,它会自动调用一个对象的__next__方法。
给定一个可迭代对象X,自身有__next__方法,调用next(X)等同于X.__next__(),但前者简单很多。例如:
>>> f = open(r'F:\002calc.py')
>>> next(f)
'temp = input("Please input a number:\\n")\n'
>>> next(f)
'num = int(temp)\n'
从技术角度来讲,迭代协议还有一点值得注意。
当for循环开始时,会通过它传给iter内置函数,以便从可迭代对象中获得一个迭代器,返回对象中有需要的next方法。