返回顶部
首页 > 资讯 > 后端开发 > Python >Python生成器、推导式之前襟后裾
  • 272
分享到

Python生成器、推导式之前襟后裾

生成器前襟后裾Python 2023-01-30 23:01:53 272人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

生成器 函数体内有yield选项的就是生成器,生成器的本质是迭代器,由于函数结构和生成器结构类似,可以通过调用来判断是函数还是生成器,如下: def fun(): yield "我是生成器" print(fun()) # 打印

生成器
函数体内有yield选项的就是生成器,生成器的本质是迭代器,由于函数结构和生成器结构类似,可以通过调用来判断是函数还是生成器,如下:

def fun():
    yield "我是生成器"
print(fun())

# 打印内容如下:
<generator object fun at 0x0000000002160ED0> 

生成器的优点就是节省内存.
python获取生成器的二种方式:

  • 通过函数获取生成器
  • 通过生成器推导式创建生成器

通过函数获取生成器

def fun(): 
    print("fun") 
    yield "生成器" 
g = fun() 
print(g)    # 打印函数名查看是否是生成器 

# 打印内容如下:
<generator object fun at 0x0000000000510ED0> 

从打印内容可以看出是生成器,但是发现生成器里面的内容没有被打印,那如何打印生成器内容呢?我们可以把生成器理解成迭代器的变异版,所以要打印生成器的内容,与迭代器类似,创建生成器对象后,可以使用生成器.__next__()来打印生成器内容,或者next()、send()等来打印生成器,如下:
使用.__next__()来打印生成器中的内容:

def fun(): 
    print("fun") 
    yield "生成器" 
    print("我在生成器的下面") 
g = fun()       # 创建生成器对象 
print(g)        # 打印生成器对象 
print(g.__next__())    # 打印生成器里面的内容 

# 打印内容如下:
<generator object fun at 0x0000000002200ED0>
fun 
生成器 

从上面的打印结果可以发现yield下面的print语句没有被打印,到yield停止了。

def fun(): 
    print("fun") 
    yield "生成器1" 
    print("我在生成器1下面") 
    yield "生成器2" 
    print("我在生成器2的下面") 
g = fun()    # 创建生成器对象 
print(g.__next__()) 
print(g.__next__()) 

# 打印内容如下:
fun 
生成器1 
我在生成器1下面 
生成器2 

由上面两个事例我们可以看出就是每next一次就执行一次yield上面的代码一次,yield下面的代码不会被执行,这就是生成器的惰性机制。
下面使用next()打印生成器内容:

def fun(): 
    print("fun") 
    yield "生成器" 
    print("我在生成器下面") 
    yield "生成器2" 
    print("我在生成器2的下面") 
g = fun() 
print(next(g)) # next(g)打印生成器内容 
print(next(g)) # next(g)打印生成器内容 

# 打印内容如下:
fun 
生成器 
我在生成器下面 
生成器2 

与.__next__()功能类似
在使用send(参数)打印生成器内容:
send方法可以给上一层的yield传递一个值,如果上一个yield没有值的话send的参数将被忽略,如果有值yield的值将被改变成当前的参数,还有需要注意的地方就是如果send(参数)做为第一次迭代,由于上一层没有yield,所以没有办法传参,会导致出现错误,错误内容如下:
TypeError: can't send non-None value to a just-started generator
我们将send(None)作为第一次调用即可,然后在第二次调用时可以传适当的参数。如下:

def fun(): 
    print("fun") 
    val = yield "生成器" 
    print("我在生成器下面") 
    print(val) 
    yield "生成器2" 
    print("我在生成器2的下面") 
    yield "生成器3" 
    print("我在生成器3的下面") 
g = fun() 
print(g.send(None)) 
print(g.send("send")) 
print(g.send("send2")) 

# 打印内容如下:
fun 
生成器 
我在生成器下面 
send 
生成器2 
我在生成器2的下面 
生成器3 

使用for循环打印生成器所有内容。

def fun(): 
    print("fun") 
    yield "生成器" 
    print("我在生成器下面") 
    yield "生成器2" 
    print("我在生成器2的下面") 
    yield "生成器3" 
    print("我在生成器3的下面") 
g = fun() # 创建生成器对象 
for g_buf in g: # 使用for循环打印生成器对象 
    print(g_buf) 

# 打印内容如下
fun
生成器
我在生成器下面
生成器2
我在生成器2的下面
生成器3
我在生成器3的下面

yield可以返回任何数据类型,这里以列表为事例:

def fun(): 
    list_1 = [1,2,3,4,5] 
    yield list_1 # 将整个列表作为返回值传给生成器对象
g = fun() # 创建生成器对象 
print(g.__next__()) # 打印生成器对象 

# 打印内容如下:
[1, 2, 3, 4, 5] 

如果想要yield从列表中每次返回一个元素可以使用yield from 列表来实现,如下:

def fun(): 
    list_1 = [1,2,3,4,5] 
    yield from list_1 
g = fun() # 创建生成器对象 
print(g.__next__()) # 打印生成器对象内容 

# 打印内容如下:
1 

可以发现只打印了列表中的一个元素,可以使用for循环打印所有内容:

def fun(): 
    list_1 = [1,2,3,4,5] 
    yield from list_1 
g = fun() 
for g_buf in g: 
print(g_buf) 

# 打印内容如下:
1 
2 
3 
4 
5 

相当于执行了5次print(g.__next__())  打印生成器所有内容。


推导式:
列表推导式:
如给list_1列表赋值1-20,常规做法如下:

list_1 = [] 
for num in range(20): 
    list_1.append(num) 
print(list_1) 

# 打印内容如下:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

列表list_1和list_2的推导式如下:

list_1 = [num for num in range(20)] 
list_2 = ["Python: %s" % num for num in range(5)]
print(list_1) 
print(list_2) 

# 打印内容如下:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
['Python: 0', 'Python: 1', 'Python: 2', 'Python: 3', 'Python: 4'] 

列表推导式还可以进行筛选,如下:

list_1 = [num for num in range(20) if num < 5 or num == 15]
print(list_1) 

# 打印内容如下:
[0, 1, 2, 3, 4, 15] 

升级一点,将一个嵌套列表中以"a"开头和以"h"开头的元素存放在一个空列表中,基础写法如下:

names = [['abc', 'abb', 'zzz'],["hello","world","xiaoming"]] 
list_names = [] 
for name_1 in names: 
    if type(name_1) == list: 
        for name_2 in name_1: 
            if name_2.startswith("a") or name_2.startswith("h"):
                list_names.append(name_2) 
print(list_names) 

# 打印内容如下:
['abc', 'abb', 'hello']         

使用列表推导法:

names = [['abc', 'abb', 'zzz'],["hello","world","xiaoming"]] 
list_names = [name_2 for name_1 in names if type(name_1) for name_2 in name_1 if name_2.startswith("a") or\ 
name_2.startswith("h")] 

# 打印内容如下:
['abc', 'abb', 'hello'] 

生成器推导式:
与列表推导式类似,只不过列表是使用[],生成器推导式使用的是()。

g_1 = (num for num in range(20)) 
print(g_1) 
print(g_1.__next__()) 
print(g_1.__next__()) 

# 打印内容如下:
<generator object <genexpr> at 0x00000000026A0ED0>
0 
1 

从打印内容和使用__next__()方法可以看出g_1是列表表达式。
使用for循环打印生成器对象:

g_1 = (num for num in range(20)) 
for num in g_1: 
  print(num) 

生成器的筛选与列表推导式用法一样,只不过是()。
如下:过滤1-20内的所有偶数。

g_1 = (num for num in range(20) if num % 2 == 0) 

升级:与上面列表推导式升级练法类似。

names = [['abc', 'abb', 'zzz'],["hello","world","xiaoming"]] 
list_names = (name_2 for name_1 in names if type(name_1) for name_2 in name_1 if name_2.startswith("a") or\ 
name_2.startswith("h")) # 创建生成器对象 
print(list_names) 
for buf in list_names: 
    print(buf) 

# 打印内容下:
<generator object <genexpr> at 0x0000000002150ED0> 
abc 
abb 
hello

生成器表达式和列表推导式的区别:

  • 列表推导式比较耗内存,一次性加载全部数据,生成器表达式几乎不占用内存,使用的时候才分配和使用内存。
  • 得到的值不一样,列表推导式得到的是一个列表全部数据,生成器表达式获取的是一个生成器。

字典推导式:

list_1 = ["电视剧","电影"] 
list_2 = ["上海滩","黄飞鸿"] 
dict_1 = {list_1[i]:list_2[i] for i in range(len(list_1))} 
print(dict_1) 

# 打印内容如下:
{'电视剧': '上海滩', '电影': '黄飞鸿'} 

集合推导式:
集合的特点:无序、不重复所以集合推导式自带去重功能。

list_1 = [1,2,3,4,2,3,5] 
set_1 = {i for i in list_1} # 集合推导式 
print(set_1) 

# 打印内容如下:
{1, 2, 3, 4, 5}

总结:

  • 推导式有列表推导式、生成器推导式、字典推导式、集合推导式。
  • 生成器表达式:(结果 for 变量 in 可迭代对象 if 条件筛选)
  • 生成器表达式可以直接获取到生成器对象,生成器对象具有惰性,每次只能打印一个生成器内容,可以使用for循环打印生成器所有的内容。

--结束END--

本文标题: Python生成器、推导式之前襟后裾

本文链接: https://lsjlt.com/news/180916.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Python生成器、推导式之前襟后裾
    生成器 函数体内有yield选项的就是生成器,生成器的本质是迭代器,由于函数结构和生成器结构类似,可以通过调用来判断是函数还是生成器,如下: def fun(): yield "我是生成器" print(fun()) # 打印...
    99+
    2023-01-30
    生成器 前襟后裾 Python
  • Python全栈之推导式和生成器
    目录1.推导式2.推导式练习3.集合_字典推导式4.生成器4.1生成器表达式4.2生成器函数5.小练习总结1. 推导式 # ### 推导式 : 通过一行循环判断遍历出一些列数据的...
    99+
    2024-04-02
  • day15(PYTHON)推导式{生成器
    #[每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型] #遍历之后挨个处理 #[满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件] #筛选功能 # #30以内所有能被3整...
    99+
    2023-01-30
    生成器 PYTHON
  • Python生成器/生成器函数/推导式/
    1. 生成器   生成器的本质就是迭代器   在python中有三种⽅方式来获取⽣生成器:     1. 通过生成器函数     2. 通过各种推导式来实现⽣成器     3. 通过数据的转换也可以获取生成...
    99+
    2023-01-31
    生成器 函数 Python
  • 生成器及推导式
    一、生成器——自己写的函数 1、只要有yield关键字的函数都是生成器函数 2、yield关键字不能与return关键字同时使用 3、return结束函数,yield不结束函数,生成器函数执行之后得到一个生成器作为返回值 return与y...
    99+
    2023-01-31
    器及
  • Python进阶之列表推导与生成器表达式详解
    目录内置序列类型列表推导与生成器表达式列表推导生成器表达式总结在python学习的过程中,我们最先接触到的就是python的数组,元组,字典等基础类型,但很少有人深入讨论python...
    99+
    2023-05-16
    Python列表推导 生成器表达式 Python 列表推导 Python 生成器表达式
  • Python全栈推导式和生成器怎么实现
    本篇内容主要讲解“Python全栈推导式和生成器怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python全栈推导式和生成器怎么实现”吧!1. 推导式# ### 推导...
    99+
    2023-06-21
  • Python 推导式、生成器与切片问题解决思路
    推导式、生成器与切片 一、实验要求 1.理解并掌握序列中的常用操作。2.理解并掌握推导式、切片等用法并能解决实际问题。 二、实验内容 1,编写程序,测试字符的出现频率。 #u...
    99+
    2024-04-02
  • Python推导式、生成器与切片问题怎么解决
    本篇内容介绍了“Python推导式、生成器与切片问题怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、实验要求理解并掌握序列中的常用...
    99+
    2023-06-29
  • python中列表推导式与生成器表达式对比详解
    目录概述列表推导式生成器表达式使用场景选择参考总结概述 Python中的列表推倒式(List Comprehension) 和 生成器表达式(Generator Expression...
    99+
    2023-01-07
    python 列表推导式 python 生成器表达式
  • Python中列表推导和生成器表达式如何使用
    Python中列表推导和生成器表达式如何使用,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。 序列序列是指一组数据,按存放类型分为容器序列与扁平序列,按能否被修改分为不...
    99+
    2023-06-15
  • python3--列表推导式,生成器表达式,内置函数
    python列表推导式l = [i for i in range(10)] print(l) ll = ['选择{}'.format(i)&nb...
    99+
    2023-01-30
    生成器 表达式 函数
  • Python高级特性之切片迭代列表生成式及生成器详解
    目录切片迭代列表生成式生成器迭代器在Python中,代码越少越好、越简单越好。基于这一思想,需要掌握Python中非常有用的高级特性,1行代码能实现的功能,决不写5行代码。代码越少,...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作