列表生成式、生成器&迭代器

一、列表生成式

  先有列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求你把列表里的每个值加1,怎么实现?

方法一:

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = []
for i in a:b.append(i+1)
a = b
print(a)

  此方法内存中会同时有两份列表,因此不适合处理大规模数据。

方法二:

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for index,i in enumerate(a):
    a[index] +=1
print(a)

方法三:

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a = map(lambda x:x+1, a)   # <map object at 0x1018da5f8>
print(a)

  利用map方法根据提供的函数(lambda)对指定序列做映射。

方法四:

# 列表生成式:一行代码完成列表操作
a = [i+1 for i in range(10)] 

  列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。

# 写列表生成式时,把要生成的元素x * x放到前面,后面跟for循环,就可以把list创建出来
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]

# 用三元运算生成列表
>>> a = range(1,11)
>>> a = [i if i < 5 else i*i for i in a]
>>> a
[1, 2, 3, 4, 25, 36, 49, 64, 81, 100]

# 使用两层循环,可以生成全排列
>>> [m + n for m in ‘ABC‘ for n in ‘XYZ‘]
[‘AX‘, ‘AY‘, ‘AZ‘, ‘BX‘, ‘BY‘, ‘BZ‘, ‘CX‘, ‘CY‘, ‘CZ‘]

# 列表生成式也可以使用两个变量来生成list
>>> d = {‘x‘: ‘A‘, ‘y‘: ‘B‘, ‘z‘: ‘C‘ }
>>> [k + ‘=‘ + v for k, v in d.items()]
[‘x=A‘, ‘y=B‘, ‘z=C‘]

# 字符串操作,都变为小写
>>> L = [‘Hello‘, ‘World‘, ‘IBM‘, ‘Apple‘]
>>> [s.lower() for s in L]
[‘hello‘, ‘world‘, ‘ibm‘, ‘apple‘]

  由此可以看到,通过列表生成式可以直接创建一个列表。列表创建在内存中,因此列表容量受到内存限制。特别是对一个元素量很大的列表,仅需访问前几个元素时,尤其浪费空间。

二、生成器

  列表元素可以按照某种算法推算出来(有规律的数组),则可以在循环的过程中不断推算出后续的元素。这种方式就不必创建完整的list,可以节省大量的空间。

  定义:python中,这种一边循环一边计算的机制,称为生成器:generator。

生成器创建:将列表生成式的‘[]’改为‘()’

  创建列表生成式和生成器的区别,仅仅是最外层的[]和()。

  如果要打印出生成器的元素,可以通过nex()函数获取generator的下一个返回值。

# 生成器保存的是公式,取一次创建一次,只能往前不能后退
>>> a2 = (i for i in range(1000))
>>> a2
<generator object <genexpr> at 0x103761a98>
>>> next(a2)
0
>>> next(a2)
1

#生成器走完时,会报错:StopIteration
>>> a3 = (i for i in range(5))   # 限制5个
>>> a3
<generator object <genexpr> at 0x103761e08>
>>> next(a3)
0
>>> next(a3)
1
>>> next(a3)
2
>>> next(a3)
3
>>> next(a3)
4
>>> next(a3)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
StopIteration

  generator保存的是算法,每次调用next(g)就计算出g的下一个元素的值,直到计算出最后一个元素,没有更多的元素时,抛出StopIteration的错误。

  创建generator后,很少会调用next(),一般是通过for循环来迭代

a3 = (i for i in range(5))
for i in a3:   # 使用for循环来迭代生成器,不会出现StopIteration报错,直接结束。
    print(i)
‘‘‘
0
1
2
3
4
‘‘‘

a2 = (i for i in range(3))
while True:    # while循环不适用
    next(a2)   # 报StopIteration错误
生成器创建:一个函数定义中包含yield关键字,函数为generator

  例如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数均可由前两个数相加得到:1, 1, 2, 3, 5, 8, 13, 21, 34,....

  列表生成式写不出斐波拉契数列,但是函数却可以轻松打印:

# 用函数来写生成器,以斐波那契数列为例
# 重点是赋值语句:a,b = b,a+b
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print(b)   # 每次打印b
        a, b = b, a + b   # 0,1——>1,1——>1,2——>2,3
        n = n + 1   # n用来计数,每次自加1
    return ‘done‘

fib(10)

  赋值语句:a, b = b , a + b

  相当于:t = (b, a + b)   a = t[0]   b = t[1]   t是一个tuple

  fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

>>> def fib_g(max):
...     n, a, b = 0, 0, 1
...     while n < max:
...         print(‘before yield‘)
...         yield b   # yield 把函数的执行过程冻结在这一步,并且把b的值返回给外面的next()
...         print(b)
...         a, b = b, a+b
...         n = n + 1
...     return ‘done‘
...
>>> f = fib_g(15)  # 将函数转换为生成器,有了yeild后,函数名(参数)根本不执行
>>> next(f)
before yield
1
>>> next(f)
1
before yield
1
>>> next(f)
1
before yield
2
>>> next(f)
2
before yield
3
>>> next(f)
3
before yield
5

  这种generator和函数相似,但与函数的执行流程不同:

  函数是顺序执行,遇到return语句或最后一行函数语句就返回。

  函数转化为generator后,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

def fib_g(max):
    n, a, b = 0, 0, 1
    while n < max:
        # print(‘before yield‘)
        yield b   # yield 把函数的执行过程冻结在这一步,并且把b的值返回给外面的next()
        # print(b)
        a, b = b, a+b
        n = n + 1
    return ‘done‘
# 生成器使用意义:可以将函数执行中的状态、数据返回到外部来

data = fib_g(10)
print(data)

print(data.__next__())
print(data.__next__())
print("干点别的事")
print(data.__next__())
print(data.__next__())
print(data.__next__())
print(data.__next__())

"""
<generator object fib_g at 0x1014670f8>
1
1
干点别的事
2
3
5
8

"""

  在上例中,循环过程中不断调用yield,就会不断中断。而且需要设置循环退出条件,否则会产生无限数列。

  将函数改写为generator后,通常不会用next()来获取下一个值,而是使用for循环来迭代。

def fib_g(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b   # yield 把函数的执行过程冻结在这一步,并且把b的值返回给外面的next()
        a, b = b, a+b
        n = n + 1
    return ‘done‘

for n in fib_g(6):
    print(n)

"""
1
1
2
3
5
8
"""

  for循环调用生成器,拿不到generator的return语句的返回值,要拿到返回值,必须捕获StopIteration错误。

def fib_g(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b   # yield 把函数的执行过程冻结在这一步,并且把b的值返回给外面的next()
        a, b = b, a+b
        n = n + 1
    return ‘done‘

g = fib_g(6)
while True:
    try:
        x = next(g)
        print(‘g‘, x)
    except StopIteration as e:
        print(‘Generator return value:‘, e.value)
        break

"""
g 1
g 1
g 2
g 3
g 5
g 8
Generator return value: done
"""
生成器send方法

send方法作用:
  1、唤醒并继续执行  (next方法只有这个功能)
  2、发送一个信息到生成器内部

def range2(n):

    count = 0
    while count < n:
        print(‘count‘, count)
        count += 1
        sign = yield count
        if sign == ‘stop‘:
            break
        print("---sign", sign)
    return 3333 

new_range = range2(3)  # 0,1,2
n1 = next(new_range)
print(new_range)
new_range.send("stop")  # 生成器不再执行后两步直接终止

"""
count 0
<generator object range2 at 0x10244c0f8>
Traceback (most recent call last):
  File "/Users/.../函数生成器2.py", line 20, in <module>
    new_range.send("stop")
StopIteration: 3333
"""
通过yield实现单线程情况下实现并发运算的效果
#_*_coding:utf-8_*_
__author__ = ‘Alex Li‘

import time
def consumer(name):
    print("%s 准备吃包子啦!" %name)
    while True:
       baozi = yield

       print("包子[%s]来了,被[%s]吃了!" %(baozi,name))

def producer(name):
    c = consumer(‘A‘)
    c2 = consumer(‘B‘)
    c.__next__()
    c2.__next__()
    print("老子开始准备做包子啦!")
    for i in range(10):
        time.sleep(1)
        print("做了2个包子!")
        c.send(i)
        c2.send(i)

producer("alex")

通过生成器实现协程并行运算
三、生成器总结

生成器的创建方式
  1.列表 列表生成式
  2.函数 函数生成器 yield

yield 对比 return
  return返回并中止function
  yield返回函数,并冻结当前的执行过程
    next唤醒冻结的函数执行过程,继续执行,直到遇到下一个yield

函数有了yield之后
  1、函数名加()就变成了一个生成器
  2、return在生成器里,代表生成器的中止,直接报错

next:唤醒生成器并继续执行
send("stop"):
  1.唤醒并继续执行
  2.发送一个信息到生成器内部

python2和python3中range()方法对比

在Python2中:
  range = list

>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

  xrange = 生成器

>>> a = xrange(10)
>>> type(a)
<type ‘xrange‘>
>>> for i in a:
...     print i
...
0
1
2
3
4
5
6
7
8
9

在Python3中:
  range = genetator

>>> range(10)  # range(0,10)  生成这个公式没有正式创建
range(0, 10)
>>> type(range(10))
<class ‘range‘>

  xrange :python3中已取消该方法

四、迭代器

  可直接作用于for循环的数据类型有一下几种:

  一、集合数据类型,如:list、tuple、dict、set、str等;

  二、generator,包括生成器表达式(geneator expression)和生成器函数(generator function)两组构建方式。

  上述这些可以直接作用于for循环的对象统称为可迭代对象(Iterable)

from collections import Iterable  # 可迭代类型
# 使用isinstance()判断一个对象是否是可迭代对象
isinstance(‘abc‘, Iterable)
isinstance({}, Iterable)
isinstance((x for x in range(10)), Iterable)

isinstance(100, Iterable)  # 返回False

原文地址:https://www.cnblogs.com/xiugeng/p/8600573.html

时间: 2024-07-30 02:14:56

列表生成式、生成器&迭代器的相关文章

python列表生成式&amp;生成器&amp;迭代器

一.列表生成式 什么是列表生成式? 列表生成式是快速生成列表的一种方式.(貌似有些废话) 更专业点的说法:列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式. 在python2.7里 举个例子,要生成list [1,2,3,4,5],可以用range(1,6) >>> range(1,6) [1, 2, 3, 4, 5] 但是如果要生成[1x1,2x2,3x3,4x4,5x5]怎么做呢? 普通青年做法: >>&

python-基础 生成式 生成器 迭代器 JSON pickl

目录 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 列表生成式,是Python内置的一种极其强大的生成list的表达式. 现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1,你怎么实现? 1 >>> a 2 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 3 >>> b =

列表生成式,迭代器&amp;生成器

一.列表生成式 用例--使列表数值都加上1 1 li = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 2 li_tmp = [i+1 for i in li] 3 li = li_tmp 4 print("new list:"+str(li)) #[1, 2, 3, 4, 5, 6, 7, 8, 9,10] li_dic =  [{1:3+i,2:4+i} for i in range(5)] #[{1: 3, 2: 4}, {1: 4, 2: 5}, {1: 5,

s14 第4天 关于python3.0编码 函数式编程 装饰器 列表生成式 生成器 内置方法

python3 编码默认为unicode,unicode和utf-8都是默认支持中文的. 如果要python3的编码改为utf-8,则或者在一开始就声明全局使用utf-8 #_*_coding:utf-8_*_ 或者将字符串单独声明: a = "中文".encode("utf-8") 函数式编程 函数式编程中的函数指代的是数学中的函数. 函数式编程输入如果确定,则输出一定是确定的.函数中并没有很多逻辑运算 python是一个面向对象的语言,只是一部分支持函数式编程.

17. Python 生成式 &nbsp; 生成器 &nbsp; 迭代器

1.      生成式和生成器 列表生成式是python受欢迎的一种语法之一,通过一句简洁的语法,就能对元组元素进行过滤,还可以对得到的元素进行转换处理. 语法格式: [exp for val in collection if condition] 相当于 result = [] for val in collection: if (condition): result.append(exp) 例子: a = [x*x for x in xrange(10) if x%2 == 0] print

列表生成式,生成器

一.列表生成式 二.生成器 斐波那契数列可以用生成器来实现. 参见:廖雪峰的生成器的教程 原文地址:https://www.cnblogs.com/zhizihuakai66/p/8877315.html

列表生成式&amp;生成器表达式

一.列表生成式 def func(): return [lambda x:i*x for i in range(4)] print([j(2) for j in func()]) 结果:[6,6,6,6] 二.生成器表达式 def func(): return (lambda x:i*x for i in range(4)) print([j(2) for j in func()]) 结果:[0,2,4,6] 原文地址:https://www.cnblogs.com/gpd-Amos/p/899

5.1.24 Python之列表生成式、生成器、可迭代对象与迭代器

语法糖的概念 列表生成式 生成器(Generator) 可迭代对象(Iterable) 迭代器(Iterator) Iterable.Iterator与Generator之间的关系 一.语法糖的概念 "语法糖",从字面上看应该是一种语法."糖",可以理解为简单.简洁.其实我们也已经意识到,没有这些被称为"语法糖"的语法,我们也能实现相应的功能,而 "语法糖"使我们可以更加简洁.快速的实现这些功能. 只是Python解释器会把这

列表生成式、生成器、迭代器

一句话概念 列表生成式--可以直接在列表里进行运算 生成器--一边循环一边计算的机制,称为生成器:generator(就是生成一个不运行的函数或者列表,即数据流) 第二句:生成器与列表的区别--生成器你不知道长度,就是一个数据流:list.dict.str你知道长度 迭代器--可以被next()函数调用并不断返回下一个值的对象称为迭代器 第二句:可迭代对象--可以直接作用于for循环的对象统称为可迭代对象:Iterable 第三句:生成器一定是迭代器,迭代器不一定是生成器 列表生成式 data

学习7: 列表生成式,生成器,迭代器,可迭代对象

1) 列表生成式,即创建列表的方式 列表生成式,这里是中括号[] >>> [x*x for x in range(0,10)] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> [x * x for x in range(1, 11) if x % 2 == 0] [4, 16, 36, 64, 100] >>> [m + n for m in 'ABC' for n in 'XYZ'] ['AX', 'AY', 'AZ