迭代器随笔

一、迭代器

  1、可迭代对象(iterable)

    a>常见可迭代对象:列表、元组、字典、字符串都是可迭代的,而整数、浮点型数据、布尔数都是不可迭代的。通过for...in...这类语句迭代读取一条数据供我们使用的对象称之为可迭代对象(iterable)

    b>通过isinstance()判断一个对象是否可以迭代

      参考代码:

          

  2、可迭代对象的本质

    a>、可迭代对象的本质就是提供迭代器帮助我们对其进行迭代使用

    b>、可迭代对象取得迭代器

       可通过迭代对象(Iterable)的__iter__()魔法方法取得迭代器

    c>、如何定义可迭代类,参考代码如下:

          

          

  3、iter()和next()函数

    前者需要传入一个可迭代对象,然后,再返回一个迭代器,内部通过可迭代对象的__iter__()方法取得迭代器;后者传入一个迭代器,返回迭代器的下一个值

  4、for..in... 循环本质:就是先通过iter()函数获取可以迭代对象的迭代器,然后对获取到的迭代器不断调用next(),来获取下一个值并将其赋值给item,当遇到StopIteration的异常后循环就结束

  5、迭代器

    1、迭代器是用于迭代数据的

        记录每次访问的位置,以及返回下一个数据,迭代器通过__next__()方法取得下一个指向的值,默认从可迭代对象的第一个元素访问,知道所有元素访问结束,且迭代器只能向下迭代

    2、迭代器就是一个可迭代对象

    3、定义迭代器:

      定义类,添加__next__(), 添加__iter__()

      参考代码如下:

            

import collections


class MyClassmate(object):
def __init__(self):
self.names = []
self.position = 0

def add(self, name):
self.names.append(name)

def __iter__(self):
# 返回迭代器, 先来个空实现
return self

def __next__(self):
if self.position < len(self.names):
item = self.names[self.position]
self.position += 1
return item
else:
raise StopIteration


classmate = MyClassmate()
classmate.add('小王')
classmate.add('小李')
classmate.add('小何')
print(isinstance(classmate, collections.Iterable))
for item in classmate:
print(item)
  

  6、迭代器的应用场景
    1、用于迭代可迭代的对象数据
    2、因为迭代器是通过__next__来获取迭代的数据的,所有可以通过__next__自动生成有规律的数据,而不用在已有的数据集合去取数,避免内存资源的浪费
    

示例: 编写斐波那契数列迭代器:
要求:传入一个n值,就能输出前n个斐波那契数列值
斐波那契数列描述:
数列中第一个数为0,第二个数为1,其后的每一个数都可由前两个数相加得到:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

  7、总结:

      1、通常用 for...in能迭代出下一个数据的对象称为可迭代对象

       2、具备了__iter__方法的对象就是可迭代对象

       3、迭代器也是可迭代对象

          定义迭代器,需要添加__next__()、__iter__()方法

        4、通过迭代器可以自动生成一些规律的数据

二、生成器

  1、生成器介绍

    生成器是一种特殊的迭代器,他比迭代器更优雅,编写更加简洁

  2、创建生成器方法1

      列表生成式       

          

# 列表推导式
L=[ x*x for x in range(5)]
print(L)

# 简单的生成器的实现方式: 列表生成式 ,把列表推导式[]改为()
G=( x*x for x in range(5))
print(G)

# 生成器是迭代器,是可迭代对象
# 使用next迭代数据
print(next(G))
print(next(G))
print(next(G))
print(next(G))
print(next(G))

# 使用for ...in 迭代
G1=( x*x for x in range(10))
for item in G1:
print(item)

    b>、yield实现生成器

      1、函数中有yield,则不再是函数,而是生成器

       2、yield会产生一个断点,暂停函数,挂起函数,且保存当前状态

        3、假如yield后面紧接着一个数据,就会把该数据返回,作为next()函数或者for..in...迭代出下一个值

       4、可以通过next()唤醒生成器,让生成器从断点继续执行

        在函数中加yield,实现复杂的生成器:

            

 

c> yield实现生成器的执行过程
"""
1.生成器默认是沉睡的,可通过next唤醒生成器
2. 第一次唤醒生成器时,是从生成器(函数)的起始位置开始,直到遇到yield,就会暂停函数,挂起函数
3. 第二次唤醒生成器时,是从yield断点处开始,直到又遇到yield
4. 当生成器已经没有yield,再使用next,则抛StopIteration异常
"""

yield生成器的执行过程代码如下:

      

# 使用yield实现生成器
def fib(n):
print("--1--")
positon = 0 # 记录当前迭代的位置,初始值是0
num1,num2=0,1# 记录数列中的前两个数,初始值 是 0,1
while positon<n:
# print(num1)
print("--2--")
"""
1. 假如函数中有yield,则不再是函数,而是生成器
2. yield 会产生一个断点,暂停函数 ,挂起函数, 且保存当前状态
3. 假如yield后面紧接着一个数据,就会把数据返回,
作为next()函数或者for ...in...迭代出的下一个值
4. 可以通过next()唤醒生成器,让生成器从断点处继续执行
假如第一次唤醒生成器,则从生成器(函数)的起始位置开始
"""
yield num1
print("--3--")
num1,num2=num2,num1+num2
positon+=1 # 自加1 ,指向下一个位置
print("--4--")


# 创建生成器对象 ,生成器默认是沉睡的状态
gen=fib(3)

# 生成器也是迭代器,也是可迭代对象
# next来迭代
print("返回值:",next(gen))
print("返回值:",next(gen))
print("返回值:",next(gen))
# print("返回值:",next(gen))

"""
1.生成器默认是沉睡的,可通过next唤醒生成器
2. 第一次唤醒生成器时,是从生成器(函数)的起始位置开始,直到遇到yield,就会暂停函数,挂起函数
3. 第二次唤醒生成器时,是从yield断点处开始,直到又遇到yield
4. 当生成器已经没有yield,再使用next,则抛StopIteration异常
"""

  


4.使用send唤醒生成器(generator)
send与next唤醒生成器不同:
1. generator.send() 与next()都可以唤醒生成器,但send方法可传值给生成器的断点处
2. 使用:
next(generator) :next是内置的函数
generator.send("你好") # send是生成器中的方法
3. generator.send(None)等价于next(generator)
4. 第一次唤醒生成器时,假如使用send,则只能传None,因为刚开始执行生成器时,是没有断点的

  send与next唤醒生成器代码如下:

        

# 使用yield实现生成器
def fib(n):
print("--1--")
positon = 0 # 记录当前迭代的位置,初始值是0
num1,num2=0,1# 记录数列中的前两个数,初始值 是 0,1
while positon<n:
# print(num1)
print("--2--")
"""
1. 假如函数中有yield,则不再是函数,而是生成器
2. yield 会产生一个断点,暂停函数 ,挂起函数, 且保存当前状态
3. 假如yield后面紧接着一个数据,就会把数据返回,
作为next()函数或者for ...in...迭代出的下一个值
4. 可以通过next()唤醒生成器,让生成器从断点处继续执行
假如第一次唤醒生成器,则从生成器(函数)的起始位置开始
"""
temp=yield num1
# 1. yield num1
# 2. temp=xxx
print("传入到断点的参数:",temp)
print("--3--")
num1,num2=num2,num1+num2
positon+=1 # 自加1 ,指向下一个位置
print("--4--")


# 创建生成器对象 ,生成器默认是沉睡的状态
gen=fib(3)

# 生成器也是迭代器,也是可迭代对象
# next来迭代
# print("返回值:",next(gen))
# print("返回值:",gen.send("test"))
print("返回值:",gen.send(None))

# send方式唤醒生成器,可以向yield断点处传值
print("返回值:",gen.send("python"))
print("返回值:",gen.send("itcast"))

"""
send与next唤醒生成器不同:
1. generator.send() 与next()都可以唤醒生成器,但send方法可传值给生成器yield的断点处
2. 使用:
next(generator) :next是内置的函数
generator.send("你好") # send是生成器中的方法
3. generator.send(None)等价于next(generator)
4. 第一次唤醒生成器时,假如使用send,则只能传None,因为刚开始执行生成器时,是没有yield断点的
"""

          

posted @ 2019-02-24 22:33  宠辱不惊666  阅读(112)  评论(0编辑  收藏  举报