一、生成迭代器
迭代是Python最强大的功能之一,是访问集合元素的一种方式。之前接触到的Python容器对象都可以用for遍历。
>>>for element in [1,2,3]:
... print(element)
>>>for element in (1,2,3):
... print(element)
>>>for key in {'one':1,'two':2}:
... print(key)
>>>for char in '123':
... print(char)
>>>for line in open('myfile.txt'):
... print(line)
这种编程风格十分简洁方便。迭代器有两个基本的方法:iter函数和next函数。for语句在容器对象上调用了iter函数,该函数返回一个定义next函数的迭代对象,它将在容器中逐一访问元素。当容器遍历完毕,next函数找不到后续元素时,会引发一个StopIteration异常,告知for循环终止。
>>>L = [1,2,3]
>>>it = iter(L)
>>>it
<list_iterator at 0xa9e0630>
>>>next(it)
1
>>>next(it)
2
>>>next(it)
3
>>>next(it)
Traceback (most recent call last):
File "<ipython-input-9-2cdb14c0d4d6>", line 1, in <module>
next(it)
StopIteration
迭代器(iterator)是一个可以记住遍历的位置的对象,从第一个元素开始访问,直到所有的元素被访问完结束。要注意的是,迭代器只能往前不会后退。
要将迭代器加入到自己的类中,需要定义一个__iter__函数,它返回一个有next方法的对象。如果类定义了next函数,__iter__函数可以只返回self。仍以前面章节(创建类与对象)的Cat类为例,通过迭代器能输出对象的全部信息。
>>>class Cat():
... def __init__(self,name,age):
... self.name = name
... self.age = age
... self.info = [self.name,self.age]
... self.index = -1
... def getName(self):
... return self.name
... def getAge(self):
... return self.age
... def __iter__(self):
... print('名字 年龄')
... return self
... def next(self):
... if self.index == len(self.info)-1:
... raise StopIteration
... self.index += 1
... return self.info[self.index]
>>>newcat = Cat('coffe', 3) # 创建对象
>>>print(newcat.getName()) # 访问对象的属性
coffe
>>>iterator = iter(newcat.next,1) # 调用迭代函数输出对象的属性
>>>for info in iterator:
... print(info)
coffe
3
二、返回迭代器
1. yield
在Python中,使用生成器(generator)可以很方便的支持迭代器协议。生成器是一个返回迭代器的函数,它可以通过常规的def语句来定义,但是不用return返回,而是用yield一次返回一个结果。不像一般的函数会生成值后退出,生成器函数在生成值后会自动挂起并暂停执行状态并保存状态信息,这些信息在函数恢复时将再度有效。通过在每个结果之间挂起和继续它们的状态来自动实现迭代协议。
这里用一个实例(yield实现斐波那契数列)来区分有yield和没有yield的情况,对生成器进一步了解。
生成器函数——斐波那契数列
>>>import sys
>>>def fibonacci(n,w=0):
... a, b, counter = 0, 1, 0
... while True:
... if (counter > n):
... return
... yield a
... a, b = b, a + b
... print('%d,%d' % (a,b))
... counter += 1
>>>f = fibonacci(10,0) # f是一个迭代器,由生成器返回生成
>>>while True:
... try:
... print (next(f), end=" ")
... except :
... sys.exit()
0 1,1
1 1,2
1 2,3
2 3,5
3 5,8
5 8,13
8 13,21
13 21,34
21 34,55
34 55,89
55 89,144
生成器函数——斐波那契数列
>>>import sys
>>>def fibonacci(n,w=0):
... a, b, counter = 0, 1, 0
... while True:
... if (counter > n):
... return
... # yield a # 不执行yield语句
... a, b = b, a + b
... print('%d,%d' % (a,b))
... counter += 1
>>>f = fibonacci(10,0) # f是一个迭代器,由生成器返回生成
>>>while True:
... try:
... print (next(f), end=" ")
... except :
... sys.exit()
1,1
1,2
2,3
3,5
5,8
8,13
13,21
21,34
34,55
55,89
89,144
在调用生成器运行的过程中,每次遇到yield时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次执行next函数时从当前位置继续运行。
简而言之,包含yield语句的函数会被特地编译成生成器。当函数被调用时,他们返回一个生成器对象,这个对象支持迭代器接口。
2. 生成器表达式
列表解析一般的形式如下。
expr for iter_var in iterable if cond_expr
迭代iterable里所有内容,每一次迭代后,把iterable里满足cond_expr条件的内容放到iter_var中,再在表达式expr中应用iter_var的内容,最后用表达式的计算值生成一个列表。
例如,生成一个list来保护50以内的所有奇数。
[i for i in range(50) if i%2]
当序列过长,而每次只需要获取一个元素时,应当考虑使用生成器表达式而不是列表解析。生成器表达式的语法和列表解析一样,只不过生成器表达式是被圆括号()括起来的,而不是方括号[ ]。
(expr for iter_var in iterable if cond_expr)
三、练习
在流程控制语句中已经接触过迭代方式,而现在是面向对象过程中对象的迭代。现在将对Car类进行迭代,增加品牌(brand)和废气涡轮增压(T)两个属性,并依次输出所有属性。
参考代码:
class Car():
def __init__(self,brand, newWheelNum, newColor,T):
self.brand = brand
self.wheelNum = newWheelNum
self.color = newColor
self.T = T # T为废气涡轮增压
self.info = [self.brand,self.wheelNum,self.color,self.T]
self.index = -1
def getBrand(self):
return self.brand
def getNewheelnum(self):
return self.wheelNum
def getNewcolor(self):
return self.color
def getT(self):
return self.T
def __iter__(self):
print('品牌 车轮数 颜色 废气涡轮增压')
return self
def next(self):
if self.index == 3:
raise StopIteration
self.index += 1
return self.info[self.index]
newcar = Car('BMW',4, 'green',2.4) # 创建对象
print(newcar.getNewcolor()) # 访问属性
iterator = iter(newcar.next,1) # 调用迭代函数输出对象的属性
for info in iterator:
print(info)
Python面向对象编程系列文章两周一更!
文章未经博主同意,禁止转载!