由于大黑山艺术体育学院的原因,今天再鸽一天。
4.4:由于今天codejam的比赛,再鸽一天。
今天开始迭代。
迭代器
魔法方法__iter__
返回一个迭代器,它是包含方法__next__
的对象,我们可以创建一个表示斐波那契数列的迭代器:
class fib:
def __init__(self):
self.a=0
self.b=1
def __next__(self):
self.a,self.b=self.b,self.a+self.b
return self.a
def __iter__(self):
return self
f=fib()
for i in f:
print(i)
if i > 1000:
break
如果没有break,循环会无限进行。
通过可迭代对象调用内置函数iter,可获得一个迭代器:
it=iter([1,2,3])
print(next(it))
print(next(it))
生成器
无论编写什么程序,都可以不使用生成器,但是它强大的功能令人欲罢不能。
nested=[[1,2],[3,4],[5]] #创建一个生成器的参数
def flatten(nested):
for sublist in nested:
for element in sublist:
yield element
#先迭代所有子列表,再迭代每个子列表的元素
#包含yield的函数被成为生成器,它和return的区别是可以生成多个值,每次一个。
#每使用yield生成一个值后,函数都将冻结,即在此停止(可以理解为类似C的static 变量),下次从停止的地方开始执行
print(list(flatten(nested)))
#对生成器进行迭代
for i in flatten(nested):
print(i)
如果层层嵌套,我们可以递归实现:
nested=[[[1],2],[3,4],[5,[6,[7]]]]
def flatten(nested):
try:
for sublist in nested:
for element in flatten(sublist):
yield element
except TypeError:
yield nested
print(list(flatten(nested)))
但是上述生成器对字符串对象会引发一些问题,我们可以对其进行改进:
nested=["foo",["bar","java",["c++","C#"]]]
def flatten(nested):
#不迭代字符串
try: nested + ""
except TypeError :pass
else:raise TypeError
try:
for sublist in nested:
for element in flatten(sublist):
yield element
except TypeError:
yield nested
print(list(flatten(nested)))
yield意味着应生成一个值,return将停止执行。相比迭代器,生成器的优势是节省内存空间。
生成器可以使用send从外界接收值:
def re(val):
while 1:
n=(yield val)#如果不使用返回值可以不括,但建议加括号
if n is not None: val=n
r=re(55)
print(next(r))
print(r.send("hello"))
生成器还有throw和close方法。throw用于在生成器中引发异常,可以提供一个异常类型、一个可选值和一个traceback对象。close用于停止生成器。
明天将解决一个经典的问题——八皇后问题,属于进阶操作,初步了解可直接忽略。