Python进阶----Sixth

可迭代的对象、迭代器和生成器

1.理论

1.所有Python序列都可以迭代
2.语言内部使用iter()内置函数处理可迭代对象
3.若没有实现iter()但是实现了__getitem__方法, Python会创建一个迭代器尝试迭代

迭代原理

a = [1, 2]
for i in a:                            
    print(i)          

等价于

a = [1, 2]
result = iter(a)
print(next(result))
print(next(result))           当迭代完所有元素后,再次迭代会报错
                              此时迭代器为空,重新获取迭代器才可以迭代
                              
print(next(result))           结果与上述相同

Python从可迭代的对象中获取迭代器      result = iter(a)   a 是可迭代的对象, result是迭代器

2.典型的迭代器

class Sen:
    ""
    生产可迭代对象
    ""
    def __init__(self, words):
        self.words = words

    def __iter__(self):                    实现迭代方法
        return SenIter(self.words)


class SenIter:
    ""
    迭代器
    ""
    def __init__(self, words):
        self.words = words
        self.index = 0

    def __next__(self):
        try:
            word = self.words[self.index]
        except IndexError:
            raise StopIteration()
        self.index += 1
        return word

    def __iter__(self):
        return self                       返回迭代器本身


obj = Sen([1, 2, 3])
for i in obj:
    print(i)

1 2 3

可迭代的对象须有__iter__方法,每次都实例化一个新的迭代器,不能实现__next__方法
迭代器需实现__next__方法以及__iter__方法,迭代器一直可以迭代

3.生成器函数

class Sen:
    def __init__(self, words):
        self.words = words

    def __iter__(self):                   生成器函数
        for word in self.words:
            yield word
        return


功能相同,此时迭代器是生成器对象,每次调用__iter__方法都会自动创建
__iter__方法是生成器函数

生成器也是迭代器,工作原理如下

def gen():
    yield 1
    yield 2
    yield 4

    
result = gen()
print(next(result))
print(next(result))
print(next(result))

1 2 4

4.生成器表达式

优点:随取随用,节省内存
只有在进行迭代时才读取,惰性机制

实现一个等差数列

def gg(begin, step, end):
    result = type(begin+step)(begin)              赋值并类型转换
    forever = end is None                         若为None则认定为无穷数列
    index = 0                    
    while forever or result < end:
        yield result
        index += 1
        result = begin + step * index


res = gg(1, 1/3, end=None)                        迭代则输出

利用标准库实现

import itertools


def gg(begin, step, end):
    first = type(begin+step)(begin)
    ap = itertools.count(first, step)                      生成迭代器
    if end is not None:
        ap = itertools.takewhile(lambda x: x < end, ap)    限制结束点
    return ap


res = gg(1, 1/3, 2)

5.初识 yield from

1.yield from 能代替内层的for循环,节省代码量
2.创建通道,把内层生成器直接与外层生成器的客户端联系起来

代码

def chain(*it):
    for i in it:                      等价于   for i in it:
        yield from i                              for j in i:
                                                      yield j

s = 'abc'
t = range(3)
print(list(chain(s, t)))

['a', 'b', 'c', 0, 1, 2]

6.iter函数的另一种用法

from random import randint


def d():
    return randint(1, 6)


res = iter(d, 1)            第一个参数必须是可调用的对象,不断产值 
for i in res:               第二个参数是标记值,当可调用对象返回这个值时程序退出
    print(i)

3 2 5 5

一个意外小测试

对于 any 和 all函数来说,这两个函数会短路,即一确定结果就立即停止使用迭代器
g = (n for n in [0, 0.0, 6, 9])     一个生成器

print(any(g))                       循环到 6 得到结果,立即停止
print(next(g))                      输出下一个值 9
                                    若在最后一个值得到结果则返回结果,抛出停止迭代

Finally 生成器实现斐波那契数列

def f():
    a, b = 0, 1
    while True:
        time.sleep(0.5)             便于观察
        yield a
        a, b = b, a + b


for i in f():
    print(i)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值