一、生成器函数

1、生成器

就是自己用python代码写的迭代器,生成器的本质就是迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)。

2、构建生成器的两种方式

1,生成器函数:跟常规函数定义类似,但是,使用yield语句而不是return语句返回结果。
yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。

2,生成器表达式:类似于列表推导,但是,返回的是生成器的一个对象,
而不是一次构建一个结果列表。

3、生成器函数

3-1、先看一般的函数

def func1(x):
x += 1
return x
func1(5) #函数的执行命令,并且接收函数的返回值。
print(func1(5)) #

3-2、再看生成器函数

def func1(x):
x += 1
print(666)
yield x
x +=2
print(777)
print(x)
yield 'xiaobai'
x +=3 g = func1(5) # 此时的func1(5)不会执行函数,因为它只是生成器函数对象
print(g) # <generator object func1 at 0x0000025E5D618780>
print(g.__next__()) #666 6
print(next(g)) #777 8 xiaobai

3-3、yield与return的区别

return:结束函数,给函数的执行者返回值
yield:不会结束函数,一个next对应一个yield,
执行yield上面的代码并给 生成器对象.__next__() 返回值

3-4、生成器函数与迭代器的区别
区别1:自定制的区别
迭代器由可迭代对象转化而来,已经‘写死了’

l1 = [1,2,3,4,5]
l1.__iter__()

生成器可用自定制函数来定制

def func1(x):
x += 1
yield x
x += 3
yield x
x += 5
yield x
g1 = func1(5)
print(g1.__next__())
print(g1.__next__())
print(g1.__next__())

区别2:内存级别的区别。
迭代器是需要可迭代对象进行转化,可迭代对象非常占内存。
生成器直接创建,不需要转化,从本质就节省内存。

def func1():
for i in range(1000000):
yield i
g1 = func1()
for i in range(50):
print(g1.__next__()) #一个next取一次值,可用for循环取值

3-5、send与next
先看例子:

def func1():
print(1)
count = yield 6 print(count)
print(2)
count1 = yield 7 print(count1)
print(3)
yield 8 g = func1()
print(g.__next__()) #1 6
print(g.send('xiaobai')) #xiaobai 2 7
print(g.send('xiaigou')) #xiaogou 3 8

总结:
send与next一样,也是对生成器取值(执行一个yield)的方法。
send可以给上一个yield 传值。
注意小坑:
1,第一次取值只能用next
2,最后一个yield不可能得到send传的值

3-6、生成器close()方法

def fun():
for i in range(5):
yield i
g = fun()
print(g.__next__())
print(g.__next__())
print(g.__next__())
g.close() # 直接把生成器的值取(删)完了,后面就不能再取值
print(g.__next__()) # 报错 a = (i for i in range(4))
print(a.__next__())
print(a.__next__())
a.close()
print(a.__next__()) #报错

3-7、生成器函数的应用例子
要制作一批量很大的衣服,用普通的函数只能一次全部制作完:

def cloth1(n):
for i in range(n+1):
print('衣服%s号' % i)
cloth1(100000) #一次全部制作完了

而用生成器函数,需要制作多少就先制作多少:

def cloth2(n):
for i in range(1,n+1):
yield '衣服%s号' % i
g = cloth2(10000) 先制作50件:
for i in range(50):
print(g.__next__()) #衣服1号,衣服2号,衣服3号...衣服50号 再制作50件:
for i in range(50):
print(g.__next__()) #衣服51号,衣服52号,衣服53号...衣服100号

3-8、生成器的取值方式

def func1():
for i in range(50):
yield i g1 = func1() # 生成器对象 # 方式一:一个next取一次值
for i in range(40):
print(g1.__next__()) # 0-39 # 方式二:直接循环生成器对象,把生成器全部内容一条条输出
for i in g1:
print(i) # 0-49

二、列表推导式,生成器表达式

1、普通方法创建一个元素为1到100的列表

l1 = []
for num in range(1,101):
l1.append(num)
print(l1)

2、列表推导式:一行代码几乎搞定你需要的任何的列表

2-1、两种方式:
  循环模式
  筛选模式

2-2、循环模式:[变量(加工后的变量) for 变量 in iterable]

#1到100的列表
l = [i for i in range(1,101)]
print(l) #[1,2,3,4...100] #python1到python15的列表
l2 = ['python%s' % i for i in range(1,16)]
print(l2) #[python1,python2,python3...python15,] #1到10的平方
l3 = [i*i for i in range(1,11)]
print(l3) #[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

2-3、筛选模式 [变量(加工后的变量) for 变量 in iterable if 条件]

#30以内的偶数
l4 = [i for i in range(1,31) if i % 2 == 0]
print(l4) #[2, 4, 6, 8,10,...28, 30] #30以内能被3整除的数
l5 = [i for i in range(1,31) if i % 3 == 0]
print(l5) #[3, 6, 9, 12, 15, 18, 21, 24, 27, 30] #30以内能被3整除的数的平方
l6 = [i**2 for i in range(1,31) if i % 3 == 0]
print(l6) #[9, 36, 81, 144, 225, 324, 441, 576, 729, 900] #找出列表中含有两个'e'的元素
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
l7 = [j for i in names for j in i if j.count('e') == 2]
print(l7) #['Jefferson', 'Wesley', 'Steven', 'Jennifer']

2-4、列表推导式优缺点
优点:一行解决,方便。
缺点:容易着迷,不易排错,不能超过三次循环。
列表推导式不能解决所有列表的问题,所以不要太刻意用。

3、生成器表达式:将列表推导式的[]换成()即可

g = (i for i in range(100000000000))
print(g) #生成器表达式左边的变量g是生成器对象
print(g.__next__()) #
print(g.__next__()) #
print(g.__next__()) # 上面代码相当于:
def func():
for i in range(100000000000):
yield i
g = func() #生成器对象
print(g.__next__())
print(g.__next__())
print(g.__next__())

4、扩展

4-1、字典推导式

# 例一:将一个字典的key和value对调
dic = {'a': 10, 'b': 34}
new_dic = {dic[k]: k for k in dic}
print(new_dic)
# 结果:
# {10: 'a', 34: 'b'} # 例二:合并大小写对应的value值,将k统一成小写
dic = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
new_dic = {k.lower():dic.get(k.lower(),0) + dic.get(k.upper(),0) for k in dic}
print(new_dic)
# 结果:
# {'a': 17, 'b': 34, 'z': 3}

4-2、集合推导式

# 例一:计算列表中每个值的平方,自带去重功能
set1 = {x**2 for x in [1, -1, 2]}
print(set1)
# 结果:
# {1, 4}

4-3、集合推导式和字典推导式的区别

相同点:外层都是使用大括号{}
不同点:返回的形式是 key:values 形式的就是字典,返回的形式是 values1,values2...形式的是集合
# 集合推导式
set1 = {x**2 for x in (1, -1, 2)}
print(set1,type(set1)) # {1, 4} <class 'set'> # 字典推导式
dic1 = {x**2:x for x in (1, -1, 2)}
print(dic1,type(dic1)) # {1: -1, 4: 2} <class 'dict'>

4-4、练习题

# 例1:  过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
l1 = [i.upper() for i in ['asdf','a','b','qwe'] if len(i) >= 3]
print(l1)
# 结果:
# ['ASDF', 'QWE'] # 例2: 求(x,y)其中x是0-5之间的偶数,y是0-5之间的奇数组成的元组列表
l2 = [(x,y) for x in range(6) if x % 2 ==0 for y in range(6) if y % 2 == 1]
print(l2)
# 结果:
# [(0, 1), (0, 3), (0, 5), (2, 1), (2, 3), (2, 5), (4, 1), (4, 3), (4, 5)] # 例3: 求M中3,6,9组成的列表
M = [[1,2,3],[4,5,6,24,3],[7,8,9,12,9]]
l3 = [j for i in M for j in i for z in [3,6,9] if j / z == 1 ]
print(l3)
# 结果:
# [3, 6, 3, 9, 9]

python之生成器和列表推导式的更多相关文章

  1. 《Python》 生成器和列表推导式

    一.初识生成器: 生成器就是自己用Python代码写的迭代器,生成器的本质就是迭代器. 1.Python中提供的生成器: 1.生成器函数: 使用yield语句而不是return语句返回结果.yield ...

  2. python之生成器(~函数,列表推导式,生成器表达式)

    一.生成器 概念:生成器的是实质就是迭代器 1.生成器的贴点和迭代器一样,取值方式也和迭代器一样. 2.生成器一般由生成器函数或者声称其表达式来创建,生成器其实就是手写的迭代器. 3.在python中 ...

  3. Python进阶(四)----生成器、列表推导式、生成器推导式、匿名函数和内置函数

    Python进阶(四)----生成器.列表推导式.生成器推导式.匿名函数和内置函数 一丶生成器 本质: ​ 就是迭代器 生成器产生的方式: ​ 1.生成器函数

  4. Python-02 生成器表达式,列表推导式

    列表推导式和生成器表达式 列表推导式,生成器表达式1,列表推导式比较直观,占内存2,生成器表达式不容易看出内容,省内存. [ 变量(加工后的数据) for  变量i  in 可迭代的数据类型 ] 列表 ...

  5. python全栈开发day13-迭代器、生成器、列表推导式等

    昨日内容:函数的有用信息.带参数的装饰器.多个装饰器修饰一个函数 迭代器 可迭代对象:内部含有__iter__方法 迭代器 定义:可迭代对象.__iter__()就是迭代器,含有__iter__且__ ...

  6. python基础学习Day12 生成器、列表推导式、字典的表达式、字典键值对的互换、集合推导式

    一.生成器 1.1 生成器:就是(python)自己用代码写的迭代器,生成器的本质就是迭代器. 1.2 生成器函数 def func1(x): x += print() yield x print() ...

  7. python基础(14):生成器、列表推导式

    1. 生成器 什么是⽣成器?⽣成器实质就是迭代器. 在python中有三种⽅式来获取⽣成器: 1. 通过⽣成器函数 2. 通过各种推导式来实现⽣成器 3. 通过数据的转换也可以获取⽣成器 ⾸先,我们先 ...

  8. 【python】 迭代器、生成器、列表推导式

    一.可迭代对象.迭代器 1.可以被for循环的数据类型(可迭代对象): 字符串(str).列表(list).字典(dict).元祖(tuple).range() 2.迭代器 2.1 将可迭代对象==& ...

  9. python基础之生成器,生成器函数,列表推导式

    内容梗概: 1. 生成器和生成器函数. 2. 列表推导式. 1.生成器函数1.1 生成器函数. 就是把return换成yield def gen(): print("爽歪歪") y ...

随机推荐

  1. jsp基础语言-jsp声明

    jsp声明的语法格式:<%! 声明代码 %> jsp声明的意义:用来定义在程序中使用到的变量.方法等.最后要以“:”结尾. jsp声明举例: <%! int a=100,b=200; ...

  2. RN开发中的报错以及告警

    报错一: Attempted to transition from state `RESPONDER_INACTIVE_PRESS_IN` to `RESPONDER_ACTIVE_LONG_PRES ...

  3. Go-Ethereum 1.7.2 结合 Mist 0.9.2 实现代币智能合约的实例

    目录 目录 1.什么是 Mist 2.Mist 在哪里下载? 3.Mist 有哪些依赖? 4.如何安装 Mist? 4.1.安装 Mist 依赖工具包 4.2.安装 Mist 4.3.启动 Mist, ...

  4. PostgreSql 查询表结构和说明

    select (select relname from pg_class where oid=a.attrelid) relname , () as comment from pg_class whe ...

  5. 【原】Java学习笔记016 - 面向对象

    package cn.temptation; public class Sample01 { public static void main(String[] args) { // this 关键字 ...

  6. c/c++ 网络编程 UDP 设定MTU

    网络编程 UDP 设定MTU MTU(Maximun Transmisson Unit):一次送信的最大size. 在程序里动态改变MTU.注意:程序运行需要root权限. 程序运行的方法: sudo ...

  7. js 学习之路6: if...else...条件语句的使用

    1.1 if (...) { ... } else { ... } <!DOCTYPE html> <html> <meta http-equiv="Conte ...

  8. redis.clients.jedis.exceptions.JedisDataException: ERR invalid DB index

    添加redis配置文件, 启动后,调用报错  redis.clients.jedis.exceptions.JedisDataException: ERR invalid DB index ERR i ...

  9. #020PAT 没整明白的题L1-009 N个数求和 (20 分)

    后面的测试点过不去,两个错误一个超时. 目前未解决   L1-009 N个数求和 (20 分)   本题的要求很简单,就是求N个数字的和.麻烦的是,这些数字是以有理数分子/分母的形式给出的,你输出的和 ...

  10. Redis学习笔记(3)——Redis的命令大全

    Redis是一种nosql数据库,常被称作数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted se ...