Python 生成器,列表推导

生成器

何为生成器?生成器就是自己用python代码写的迭代器,生成器的本质就是迭代器

1 l1 = [1,2,3]
2 iter1 = iter(l1)
用以下两种方式构建一个生成器
1. 通过生成器函数
2. 生成器表达式

生成器函数

什么是生成器函数,它与普通的函数有什么区别?首先,我们举一个简单的函数,如:
1 def func1(x):
2     x += 1
3     return x
4 func1(5)     # 函数的执行命令,并且接受函数的返回值
5 print(func1(5))   # 6
再来看一个函数,该函数表示的是生成器函数:
 1 def func1(x):
 2     x += 1
 3     print(111)
 4     yield  x
 5     x += 2
 6     print(222)
 7     yield 'colin'
 8     x += 3
 9 g_obj = func1(5)  # 生成器函数对象
10 print(g_obj)  # <generator object func1 at 0x000001B56D891F10>
11 print(g_obj.__next__())   # 6
12 print(g_obj.__next__())   # colin
从上面分析可以知道,一个next对应一个yield
yield 将值返回给 生成器对象.__next__()
区别yield与return
return 表示结束函数,给函数的执行者返回值
yield 不会结束函数,一个next对应一个yield,给生成器对象.__next()返回值。

生成器vs迭代器

区别1:自定制区别
 1 l1 = [1,2,3,4,5]
 2 l1.__iter__()
 3 def func1(x):
 4     x += 1
 5     yield x
 6     x += 3
 7     yield x
 8     x += 5
 9     yield
10 g1 = func1(5)
11 print(g1.__next__()) # 6
12 print(g1.__next__()) # 9
13 print(g1.__next__()) # 无返回值 None

区别2:内存级别的区别

迭代器是需要可迭代对象进行转化,可迭代对象非常占内存
生成器直接创建,不需要转化,从本质上就节省内存
1 def func1():
2     for i in range(1,10000):
3         yield i
4 g1 = func1()
5 for i in range(50):
6     print(g1.__next__()) # 每next一次,就取一个值

区别:next() 与 send()

 1 def func1():
 2     print(1)
 3     count = yield 6
 4     print(count)
 5     print(2)
 6     count1 = yield 7
 7     print(count1)
 8     print(3)
 9     yield 8
10 g = func1()
11 next(g)
12 g.send('colin')
13 g.send('Jenny')
14 g.send('taibai')
从上面的例子可以看出,send 与next一样,也是对生成器取值(执行一个yield)的方法
send可以给上一个yield传值
第一次取值永远都是next
最后一个yield永远也得不到send传的值
函数直接取完所有值,所有值都直接放进内存处理
1 def cloth1(n):
2     for i in range(n+1):
3         print('衣服%s号' % i)
4 cloth1(10000)
生成器函数:next多少次,就取多少次值,非常节省内存.
1 def cloth2(n):
2     for i in range(1,n+1):
3         yield '衣服%s号' % i
4 g = cloth2(10000)
5 for i in range(50):
6     print(g.__next__())
7 for i in range(50):
8     print(g.__next__())

列表推导式

先看一个for循环例子:
1 l1 = []
2 for num in range(1, 101):
3     l1.append(num)
4 print(l1)
再来看一个例子:
l = [i for i in range(1,101)]
print(l)
又比如下面的例子:
1 l2 = ['python%s期' % i for i in range(1,16)]
2 print(l2)
3 print([i*i for i in range(1,11)])
从上面的例子中,我们可以看出,只需要一行代码就几乎可以搞定你需要的任何的列表。所以,我们称该形式为列表推导式。
第一种为循环模式,其形式为:
[变量(加工后的变量) for 变量 in iterable]

 接下来一种方式为:筛选模式,该方式表示为:

 [变量(加工后的变量) for 变量 in iterable if 条件]
l3 = [i for i in range(1,31) if i % 2 == 0]
print(l3)
print([i for i in range(1,31) if i % 3 == 0])
print([i**2 for i in range(1,31) if i % 3 == 0])
1 names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
2          ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
3 print([j for i in names for j in i if j.count('e') == 2])
列表推导式的优缺点:
优点:一行解决,方便
缺点:容易着迷,不易不易排错,不能超过三次循环。
但是,列表推导式不能解决所有列表的问题,所以不用太刻意用。
生成器表达式:将列表推导式的[]换成()即可。
1 g = (i for i in range(100000000000))
2 print(g)
3 print(g.__next__())
4 print(g.__next__())
5 print(g.__next__())
6 print(g.__next__())
7 print(g.__next__())
8 print(g.__next__())

字典:

1 mcase = {'a': 10, 'b': 34}
2 mcase_frequency = {mcase[k]: k for k in mcase}
3 print(mcase_frequency)

集合:

1 squared = {x**2 for x in [1, -1, 2]}
2 print(squared)
原文地址:https://www.cnblogs.com/colin1314/p/9506612.html