博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
迭代器随笔
阅读量:7118 次
发布时间:2019-06-28

本文共 4780 字,大约阅读时间需要 15 分钟。

一、迭代器

  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断点的
"""

          

转载于:https://www.cnblogs.com/python58/p/10428449.html

你可能感兴趣的文章
机器学习算法实践:决策树 (Decision Tree)(转载)
查看>>
slack 团队协作平台
查看>>
【C#】:浅谈反射机制 【转】
查看>>
【iCore4 双核心板_FPGA】例程五:基础逻辑门实验——逻辑门使用
查看>>
使用Nmon监控Linux的系统性能
查看>>
React-Native 之 GD (十三)数据持久化(realm) 及 公共Cell
查看>>
flask及扩展源码解读
查看>>
通俗易懂详解Java代理及代码实战
查看>>
需求工程的基本过程
查看>>
Android 版本对于 API
查看>>
Hadoop,MapReduce
查看>>
Kafka Streams简介: 让流处理变得更简单
查看>>
「mysql优化专题」90%程序员面试都用得上的索引优化手册(5)
查看>>
Django---ORM操作大全
查看>>
JAVA远程通信的几种选择(RPC,Webservice,RMI,JMS的区别)
查看>>
Python 将json字符串 进行列表化可循环
查看>>
Django Drops
查看>>
NLog自定义字段写入数据库表,示例
查看>>
SQL优化的思路及基本原则(mysql)
查看>>
data-toggle data-target
查看>>