首页 > 编程语言 >《流畅的python》— 列表推导与生成器表达式

《流畅的python》— 列表推导与生成器表达式

时间:2023-08-24 10:35:00浏览次数:45  
标签:推导 python symbol 生成器 列表 array 表达式

列表推导是构建列表(list)的快捷方式,而生成器表达式则可以用来创建其他任何类型的序列。如果你的代码里并不经常使用它们,那么很可能你错过了许多写出可读性更好且更高效的代码的机会。

很多Python 程序员都把列表推导(list comprehension)简称为listcomps,生成器表达式(generator expression)则称为genexps。我有时也会这么用。

1、列表推导

>>> symbols = '$¢£¥€¤'
>>> codes = [ord(symbol) for symbol in symbols]
>>> codes
[36, 162, 163, 165, 8364, 164]

for 循环可以胜任很多任务:遍历一个序列以求得总数或挑出某个特定的元素、用来计算总和或是平均数,还有其他任何你想做的事情。在示例2-1 的代码里,它被用来新建一个列表。

另一方面,列表推导也可能被滥用。以前看到过有的Python 代码用列表推导来重复获取一个函数的副作用。通常的原则是,只用列表推导来创建新的列表,并且尽量保持简短。如果列表推导的代码超过了两行,你可能就要考虑是不是得用for 循环重写了。就跟写文章一样,并没有什么硬性的规则,这个度得你自己把握。

2、生成器表达式

虽然也可以用列表推导来初始化元组、数组或其他序列类型,但是生成器表达式是更好的选择。这是因为生成器表达式背后遵守了迭代器协议,可以逐个地产出元素,而不是先建立一个完整的列表,然后再把这个列表传递到某个构造函数里。前面那种方式显然能够节省内存。

生成器表达式的语法跟列表推导差不多,只不过把 方括号换成圆括号 而已。下面这个示例展示了如何用生成器表达式建立元组和数组。

>>> symbols = '$¢£¥€¤'
>>> tuple(ord(symbol) for symbol in symbols) # ➊
(36, 162, 163, 165, 8364, 164)
>>> import array
>>> array.array('I', (ord(symbol) for symbol in symbols))  # ➋
array('I', [36, 162, 163, 165, 8364, 164])

➊ 如果生成器表达式是一个函数调用过程中的唯一参数,那么不需要额外再用括号把它围起来。
➋ array 的构造方法需要两个参数,因此括号是必需的。array 构造方法的第一个参数指定了数组中数字的存储方式。2.9.1 节中有更多关于数组的详细讨论。

下面这个示例则是利用生成器表达式实现了一个笛卡儿积,用以打印T恤衫的 2 种颜色和 3 种尺码的所有组合。与上一个示例不同的是,用到生成器表达式之后,内存里不会留下一个有 6 个组合的列表,因为生成器表达式会在每次 for 循环运行时才生成一个组合。如果要计算两个各有 1000 个元素的列表的笛卡儿积,生成器表达式就可以帮忙省掉运行 for 循环的开销,即一个含有 100 万个元素的列表。

>>> colors = ['black', 'white']
>>> sizes = ['S', 'M', 'L']
>>> for tshirt in ('%s %s' % (c, s) for c in colors for s in sizes): # ➊
... print(tshirt)
...
black S
black M
black L
white S
white M
white L

生成器表达式逐个产出元素,直接计算到最后一个元素,从来不会一次性产出一个含有6 个T 恤样式的列表。


3、总结:两者区别

  • 生成器表达式每次处理一个对象,而不是一口气处理和构造整个数据结构,这样做可以节省大量的内存,在处理的数据量较大时,最好考虑使用生成器表达式而不是列表推导式;
  • 得到的值不一样,列表推导式得到的是一个列表,生成器表达式获取的是一个生成器,但是你可以遍历输出。而且列表推导式可以多次迭代,生成器表达式只能单次迭代。

标签:推导,python,symbol,生成器,列表,array,表达式
From: https://www.cnblogs.com/chenxyy/p/17653510.html

相关文章

  • python-flask小结
    1.flask和django区别1.flask是一个轻量级的,django是一个重量级的,包含了很多组件,包括admin,orm等,flask虽然没有但可以引入第三方组件。2.flask是基于上下文管理做的一个应用上下文appcontext和请求上下文requestcontext管理。django只是通过参数传递。2.flask生命周期......
  • python rasa聊天机器人教程六:服务器部署
    1.准备环境:宝塔+nginx+docker首先在服务器上安装好宝塔,然后在宝塔里面安装nginx+docker2.创建站点宝塔站点里面创建一个站点 3.上传rasa项目的代码到站点目录把之前在本地运行正常的rasa项目代码上传到服务器站点目录上4.修改index.html代码修改站点目录下/www/wwwroo......
  • python - 文件md5校验
    通过md5校验文件,我们可以判断文件内容是否改变,用python实现代码如下importhashlib#1.txt为空文本withopen('1.txt','rb')asf:data=f.read()md5Old=hashlib.md5(data).hexdigest()print(md5Old)#d41d8cd98f00b204e9800998ecf8427e#1.txt内容为12......
  • Python基础
    python学习后缀.py纯Python文件.ipynbJupyterNotebook文件的扩展名,代表IpythonNotebook.pyi类型提示文件,提供代码静态类型信息,帮助开发人员进行类型检查和静态分析命名和对应py文件相同,以便编译器将二者进行关联.pycPython字节码文件的扩展名,存储已编......
  • Python结合文件名将文件复制到匹配的多个文件夹内
       本文介绍基于Python语言,针对一个文件夹下的大量栅格遥感影像文件,基于其各自的文件名,分别创建指定名称的新文件夹,并将对应的栅格遥感影像文件复制到不同的新文件夹下的方法。  首先,我们来看一下本文需要实现的需求。现有一个文件夹,其中有大量.tif格式的栅格遥感影像文件,以......
  • python3_获得文件大小
    1、os.path.getsize(file_path),返回文件字节大小,int类型。importosfile_size=os.path.getsize('/home/pi/jodie/log/jodie-test.log')print(file_size,type(file_size))#947642<class'int'>#显示文件大小为:925kB2、os.stat(file_path).st_size,返回文件字......
  • 扩展功能_代码生成器
            ......
  • python for循环
     格式:for变量in序列:执行的代码块 实例1:fruits=["apple","banana","cherry"]forfruitinfruits:print(fruit)      ......
  • python3_关于数字的一些操作记录
    1、数字整数、小数部分分离方法1:math模块提供的floor方法xs=num-math.floor(num)zs=num-xsreturn 'zhengShu: {0}, xiaoShu: {1}'.format(str(zs),str(xs))方法2:将浮点类型的数字转化为字符串zs,xs=str(num).split('.')return 'zhengShu: {0}, xiaoShu: {1}'.fo......
  • python+selenium+pytest-(3)_基本操作方法
    浏览器操作#浏览器实例化driver=webdriver.Chrome()#窗口最大化driver.maximize_window()#窗口最小化driver.miximize_window()#浏览器长、宽设置,单位:像素driver.set_window_size(100,200)#获取浏览器大小driver.get_window_size()#前进/后退/刷新driver.forwa......