十二. Python基础(12)--生成器

1 ● 可迭代对象(iterable)

An object capable of returning its members one at a time. Examples of iterables include all sequence types (such as list, str, and tuple) and some non-sequence types like dict and file and objects of any classes you define with an __iter__() or __getitem__() method.

An iterable object works as the source of items in for loops, comprehensions and tuple unpacking.

Iterables are objects that produce an iterator when they are passed to the iter() builtin.

一些iterable将所有值都存储在内存中,比如list,而另一些并不是这样,比如我们下面将讲到的iterator.

Python内置的可迭代对象:

range(),str,list,tuple,dict,set

 

2 ● 迭代器(iterator)

An object representing a stream of data. Repeated calls to the iterator's __next__ () method return successive items in the stream. When no more data are available a StopIteration exception is raised instead.

Also, Iterators are required to have an __iter__() method that returns the iterator object itself (返回迭代器对象自身), so every iterator is also iterable.


迭代器内部持有一个状态,该状态用于记录当前迭代所在的位置,以方便下次迭代的时候获取正确的元素。

python的迭代器为什么一定要实现__iter__方法?

iterator实现(implement)的__iter__是为了兼容iterable的接口,从而让iterator成为iterable的一种实现.

Python内置的迭代器:

iter(range()),iter(str),iter(list),iter(tuple),iter(dict),iter(set),reversed(list_o),map(func,list_o),filter(func,list_o),file_o

 

3 ● 判断是否为可迭代对象/迭代器

from collections import Iterable

print(isinstance('aaa', Iterable)) # True

print(isinstance('aaa'.__iter__(), Iterable)) # True, Iterator属于Iterable

from collections import Iterator

print(isinstance([1,2,3], Iterator)) # False

print(isinstance([1,2,3].__iter__(), Iterator)) #True

 

4 ● 可迭代对象协议(iterable protocol)/迭代器协议(iterator protocol)

可迭代对象协议: 对象内部实现了__iter__方法。


如何确定一个对象是否可迭代? --看是否包含__iter__()方法.

迭代器协议: 对象内部实现了__iter__()方法和__next__()方法.


更详细的说法: 对象必须提供一个next方法, 执行该方法要么返回迭代中的下一项, 要么就引起一个StopIteration异常, 以终止迭代 (只能往后走不能往前退).

__iter__()方法: 返回一个迭代器对象

__next__()方法: 返回迭代器的下一个项目

 

5● 迭代器的表象&本质

表象: Python从迭代器中一个一个的取值.

本质:把标志控制的循环

计数控制的循环统一为一种控制的循环,即迭代器控制的循环,每一次迭代操作中对迭代器的修改就等价于修改标志或计数器.

 

 

6 ● 生成器(generator)&生成器函数(generator function)&生成器表达式(generator expression)

generator: (自己实现的iterator)

Both generator functions and generator expressions are generators, by which we can build an iterator by ourseleves.

迭代器就是我们自己就可以通过生成器函数和生成器表达式实现的迭代器.

生成器一定是迭代器, 但迭代器不一定是生成器.

 


调用生成器函数时,每次执行到yield语句,生成器的状态将被冻结起来,并将结果返回__next__调用者。冻结意思是局部的状态都会被保存起来,包括局部变量绑定、指令指针。确保下一次调用时能从上一次的状态继续。

生成器的特点(同样适用于迭代器):

① 节省内存(因为惰性计算): iterate through potentially huge sequences without creating and storing the entire sequence in memory at once.

② 一个生成器只能运行一次: 生成器中的每个值只能按顺序取一次, 并且不能返回取值, 取完后就不能再从生成器中取值了;

③ 惰性运算: 生成器只有在被调用的时候才会生成相应的数据(用__next__()、 for、list调用, 或被其它函数调用), 反之就不会生成--因此python适合大数据处理

④ 无法复制一个生成器

(无论是直接复制给另一个对象, 还是进行深浅拷贝, 都不能复制生成器, 因此要再次进行迭代只能重新生成一个新的迭代器对象)

※⑤ 可以把非线性化的处理转换成线性化的方式来进行处理。

迭代器函数(generator function):

A function that has the yield keyword in its body.

1. 概念:带yield关键字的函数就是生成器函数

2. 特点(也是迭代器的特点, 见上):

3. 从生成器中取值的方法:

①__next__() 有几个yield就可以取几次

② for循环取值
正常取 for i in g:

③用其他数据类型进行强制转换, 例如, list(g)返回一个列表, 里面装着生成器中的所有内容


上面三种取值方法不要混合使用

迭代器表达式/迭代器推导式(generator expression/generator comprehension):

An expression enclosed in parenthesis using the same syntax of a list comprehension, but returning a generator instead of a list. A generator expression can be understood as a lazy version of a list comprehension.

 

7 ● 几个概念的关系

※ A generator is a subtype of iterator; an iterator is an iterable.


迭代器 = 可迭代对象.__iter__()


迭代器分为①先天的(如文件句柄); ②后天的(可迭代对象.__iter__(), 如range返回的可迭代对象)

 

8 ● 生成迭代器的两种方法

# 使用对象内置的__iter__()方法生成迭代器

L1 = [1,2,3]

I1 = L1.__iter__()

print(I1)

print(I1.__next__()) #1, python2还可以写成print I1.next(), python3还可以写成print(next(I1))

print(I1.__next__())

# 下面是容错处理:

while True:

    try:

        print(I1.__next__())

    except StopIteration:

        break

# 使用内置工厂函数生成迭代器

L1 = [1,2,3]

I2 = iter(L1)

print(I2)

print(I2.next()) # 1, 在python3中, 会提示没有next()这个方法,只能用__next__()或next(iterator)

print(I2.next())

 

9 ● for和可迭代对象和迭代器

for loop可作用于(work on)可迭代对象和迭代器.

for循环的本质:

① 循环不是迭代器的可迭代对象
:不具备__next__()方法的可迭代对象.__iter__(), 得到了一个迭代器, 然后调用迭代器的__next__()方法

② 循环迭代器:直接调用迭代器的__next__()方法

import time

start_time_1 = time.time()

for i in range(200000000):

    pass

time_cost_1 = time.time() - start_time_1

print('time_cost_1:',time_cost_1)

 

time.sleep(5)

 

import time

start_time_2 = time.time()

for i in range(200000000).__iter__():

    pass

time_cost_2 = time.time() - start_time_2

print('time_cost_2:',time_cost_2)

time_cost_1: 21.656238555908203

time_cost_2: 24.198384284973145 # 迭代器可以节省内存, 但速度不一定快.

 

10 ● 生成器表达式的案例

number_thing = (number for number in range(1, 6))

圆括号之间的是生成器推导式(generator comprehension),它返回的是一个生成器对象(generator object):

>>> type(number_thing)

<class 'generotor'>

你可以直接对生成器对象进行迭代,如下所示:

>>> for number in number_thing:

... print(number)

...

1

2

3

4

5

或者通过调用list() 函数:

>>> number_list = list(number_thing)

>>> number_list

[1, 2, 3, 4, 5]

※ A generator can be run only once. Lists, sets, strings, and dictionaries exist in memory, but a generator creates its values on the fly(即时, 立刻, 马上) and hands them out one at a time through an iterator. It doesn't remember them, so you can't restart or back up a generator.

一个生成器只能运行一次。列表、集合、字符串和字典都存储在内存中,但是生成器仅在运行中产生值,不会被存下来,所以不能重新使用或者备份一个生成器。

例如:

>>> try_again = list(number_thing)

>>> try_again

 

11 ● eager and lazy(急切和懒惰)

An iterable object that builds all its items at once. In Python, a list comprehension is eager. Contrast with lazy.

An iterable object which produces items on demand. In Python, generators are lazy. Contrast with eager.

 

12 ● 生成器最相关的面试题

① 生成器中的内容需要使用__next__()、 for、list主动获取才会生成, 反之就不会生成--惰性运算

② 使用__next__()、for、list从迭代器中取值后, 迭代器中的内容必然会减少或者完全用光.

 

13 ● 监听文件输入的内容

import time

def tail(filename):

    f = open(filename, encoding= "utf-8")

    f.seek(0,2)

    while True:

        line = f.readline()

        if not line:

            time.sleep(0.1) # 避免因为while True的原因导致内存消耗过大,

            continue

        else:

            yield line

 

tail_gen = tail("test.txt")

for line in tail_gen:

    print(line, end = "")

 

十二. Python基础(12)--生成器的更多相关文章

  1. 二十二. Python基础(22)--继承

    二十二. Python基础(22)--继承 ● 知识框架   ● 继承关系中self的指向 当一个对象调用一个方法时,这个方法的self形参会指向这个对象 class A:     def get(s ...

  2. 二十六. Python基础(26)--类的内置特殊属性和方法

    二十六. Python基础(26)--类的内置特殊属性和方法 ● 知识框架 ● 类的内置方法/魔法方法案例1: 单例设计模式 # 类的魔法方法 # 案例1: 单例设计模式 class Teacher: ...

  3. 二十五. Python基础(25)--模块和包

    二十五. Python基础(25)--模块和包 ● 知识框架   ● 模块的属性__name__ # my_module.py   def fun1():     print("Hello& ...

  4. 二十四. Python基础(24)--封装

    二十四. Python基础(24)--封装 ● 知识结构   ● 类属性和__slots__属性 class Student(object):     grade = 3 # 也可以写在__slots ...

  5. 十八. Python基础(18)常用模块

    十八. Python基础(18)常用模块 1 ● 常用模块及其用途 collections模块: 一些扩展的数据类型→Counter, deque, defaultdict, namedtuple, ...

  6. 十六. Python基础(16)--内置函数-2

    十六. Python基础(16)--内置函数-2 1 ● 内置函数format() Convert a value to a "formatted" representation. ...

  7. 『Python基础-12』各种推导式(列表推导式、字典推导式、集合推导式)

    # 『Python基础-12』各种推导式(列表推导式.字典推导式.集合推导式) 推导式comprehensions(又称解析式),是Python的一种独有特性.推导式是可以从一个数据序列构建另一个新的 ...

  8. 二. Python基础(2)--语法

    二. Python基础(2)--语法 1.实现一个简单的登录系统 '''# 形式1 n = 1 while n < 4:     name = input("请输入姓名\n" ...

  9. Tensorflow深度学习之十二:基础图像处理之二

    Tensorflow深度学习之十二:基础图像处理之二 from:https://blog.csdn.net/davincil/article/details/76598474   首先放出原始图像: ...

随机推荐

  1. 20180429 xlVBA套打单据批量复制

    Sub testCopyModelRange() Set ModelSheet = ThisWorkbook.Worksheets("单据模板") Set PrintSheet = ...

  2. 20170906xlVBA_GetEMailFromDocument

    Public Sub GetDataFromWord() AppSettings 'On Error GoTo ErrHandler Dim StartTime, UsedTime As Varian ...

  3. Sonya and Matrix CodeForces - 1004D (数学,构造)

    http://codeforces.com/contest/1004/problem/D 题意:网格图给定到中心点的曼哈顿距离数组, 求该图n,m及中心点位置 首先可以观察到距离最大值mx一定在某个角 ...

  4. MVC实战之排球计分(一)—— 需求分析与数据库设计

    此系列博客目的是制作一款排球计分程序.这系列博客讲讲述此软件的 各个功能的设计与实现. 一.需求分析: 这个程序是排球计分程序,其业务非常简单,具体如下: 1.本程序可以选择用户身份,通过不同角度记录 ...

  5. php调用oracle存储

    //todo 调用oracle 存储$config = //数据库配置文件 里面包含 用户密码和host和端口以及dbname $conn = oci_connect($config['usernam ...

  6. poj-2115-exgcd

    C Looooops Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 32062   Accepted: 9337 Descr ...

  7. BP搜索帮助,调用BP_HEAD_SEARCH组件

    1.BP类字段,GET V方法: METHOD get_v_zhsi0cnn. CREATE OBJECT rv_valuehelp_descriptor TYPE cl_bsp_wd_valuehe ...

  8. JedisClusterMaxRedirectionsException: Too many Cluster redirections

    发生环境 当时的redis集群配置:redis-trib.rb 127.0.0.1 .... redis.conf的bind是默认# 解决方案 将redis.conf的bind为局域网真实ip red ...

  9. MongoDB 教程(五):连接、新建数据库、删除数据库

    连接 启动 MongoDB 服务 只需要在 MongoDB 安装目录的 bin 目录下执行 mongodb 即可. 执行启动操作后,mongodb 在输出一些必要信息后不会输出任何信息,之后就等待连接 ...

  10. iOS 面试总结

    APP崩溃 启动秒退 在新 iOS 上正常的应用,到了老版本 iOS 上秒退最常见原因是系统动态链接库或Framework无法找到.这种情况通常是由于 App 引用了一个新版操作系统里的动态库(或者某 ...