Python面向对象编程(四)

一、生成迭代器

       迭代是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面向对象编程系列文章两周一更!


文章未经博主同意,禁止转载!

微笑


猜你喜欢

转载自blog.csdn.net/qq_40304090/article/details/80090361