Python列表解析式的正确使用方式(二)
高级解析式
条件逻辑
早些时候,我向您展示了这个公式:
python学习交流群:660193417###
new_list = [expression for member in iterable]
公式可能有些不完整。对解析式的更加完整描述增加了对可选条件的支持。将条件逻辑添加到列表解析式的最常见方法是在表达式的末尾添加条件:
new_list = [expression for member in iterable (if conditional)]
在这里,您的条件语句正好位于右边的括号中。
条件很重要,因为它们允许列表解析式过滤掉不需要的值,这在一般情况下也可以调用 filter():
numbers = [number for number in range(20) if number % 2 == 0]
print(numbers)
输出:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
正如您所看到的那样,这个解析式收集了可被 2 整除且没有余数的数字。
如果您需要更复杂的过滤器,那么您甚至可以将条件逻辑移动到单独的函数中。
def is_prime(number):
if number > 1:
for el in range(2, int(number/2)+1):
if (number % el) == 0:
return False
else:
return True
numbers = [number for number in range(20) if is_prime(number)]
print(numbers)
输出:
[2, 3, 5, 7, 11, 13, 17, 19]
您构建 is_prime(number) 以确定是否是素数并返回布尔值。接下来,您应该将函数添加到解析式的条件中。
该公式允许您使用条件逻辑从几个可能的输出选项中进行选择。例如,您有一个产品价格表,若有负数,您应将其转换为正数:
price_list = [1.34, 19.01, -4.2, 6, 8.78, -1,1]
normalized_price_list = [price if price > 0 else price*-1 for price in price_list]
print(normalized_price_list)
输出:
[1.34, 19.01, 4.2, 6, 8.78, 1,1]
在这里,您的表达式 price 有一个条件语句,如果 price > 0 else price*-1。这会告诉 Python,如果价格为正,则输出价格值;但如果价格为负,则将价格转换为正值。该功能很强大,考虑将条件逻辑视为其自身的函数的确是很有用的:
def normalize_price(price):
return price if price > 0 else price*-1
price_list = [1.34, 19.01, -4.2, 6, 8.78, -1,1]
normalized_price_list = [normalize_price(price) for price in price_list]
print(normalized_price_list)
输出:
[1.34, 19.01, 4.2, 6, 8.78, 1,1]
集合解析式
您还可以创建一个集合解析式!它基本与列表解析式相同。不同之处在于集合解析式不包含重复项。您可以通过使用花括号取代方括号来创建集合解析式:
string = "Excellent"
unique_string = {letter for letter in string}
print(unique_string)
输出:
{"E", "e", "n", "t", "x", "c", "l"}
你的集合解析式只包含唯一的字母。这与列表不同,集合不保证项目将以特定顺序存储数据。这就是为什么集合输出的第二个字母是 e,即使字符串中的第二个字母是 x。
字典解析式
字典解析式也是是类似的,但需要定义一个键:
string = "Words are but wind"
word_order = {el: ind+1 for ind, el in enumerate(string.split())}
print(word_order)
输出:
{"Words": 1, "are": 2, "but": 3, "wind": 4}
要创建 word_order 字典,请在表达式中使用花括号 ({}) 以及键值对 (el: ind+1)。
海象运算符
Python 3.8 中引入的海象运算符允许您一次解决两个问题:为变量赋值,返回该值。
假设您需要对将返回温度数据的 API 应用十次。您想要的只是 100 华氏度以上的结果。而每个请求可能都会返回不同的数据。在
这种情况下,没有办法在 Python 中使用列表解析式来解决问题。可迭代成员(如果有条件)的公式表达式无法让条件将数据分配
给表达式可以访问的变量。
海象运算符解决了这个问题。它允许您在执行表达式的同时将输出值分配给变量。以下示例显示了这是如何实现的,使用
get_weather_data() 生成伪天气数据:
import random
def get_weather_data():
return random.randrange(90, 110)
hot_temps = [temp for item in range(20) if (temp := get_weather_data()) >= 100]
print(hot_temps)
输出:
[108, 100, 106, 103, 108, 106, 103, 104, 109, 106]
什么时候不要使用解析式
列表解析式非常有用,它可以帮助您编写清晰且易于阅读和调试的代码。但在某些情况下,它们可能会使您的代码运行速度变慢或使用更多内存。如果它让您的代码效率更低或更难理解,那么可以考虑选择另一种方式。
注意嵌套的解析式
可以通过嵌套解析式以创建列表、字典和集合的组合集合(译者注:这个集合不是指 set 对象类型,而是 collection,泛指容
器)。例如,假设一家公司正在跟踪一年中五个不同城市的收入。存储这些数据的完美数据结构可以是嵌套在字典解析式中的列表解析式。
cities = ['New York', 'Oklahoma', 'Toronto', 'Los Angeles', 'Miami']
budgets = {city: [0 for x in range(12)] for city in cities}
print(budgets)
输出:
{
"NewYork": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"Oklahoma": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"Toronto": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"LosAngeles": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"Miami": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}
您使用字典解析式创建了 budgets 容器。该表达式是一个键值对,其中包含另一个解析式。此代码将快速生成城市中每个 city 的数据列表。
嵌套列表是创建矩阵的常用方法,通常用于数学目的。查看下面的代码块:
matrix = [[x for x in range(7)] for y in range(6)]
print(matrix)
输出:
[
[0, 1, 2, 3, 4, 5, 6],
[0, 1, 2, 3, 4, 5, 6],
[0, 1, 2, 3, 4, 5, 6],
[0, 1, 2, 3, 4, 5, 6],
[0, 1, 2, 3, 4, 5, 6],
[0, 1, 2, 3, 4, 5, 6]
]
外部列表解析式 [… for y in range(6)] 创建了六行,而内部列表解析式 [x for x in range(7)] 将用值填充这些行中的每一行。
到目前为止,每个嵌套解析式的目标都是真正且直观的。但是,还有一些其他情况,例如创建扁平化的嵌套列表,其中的逻辑可以使您的代码非常难以阅读。让我们看下面的例子,使用嵌套列表解析式来展平一个矩阵:
matrix = [
[0, 1, 0],
[1, 0, 1],
[2, 1, 2],
]
flat = [num for row in matrix for num in row]
print(flat)
输出:
[0, 1, 0, 1, 0, 1, 2, 1, 2]
扁平化矩阵的代码确实很简洁,但是太难理解了,您应该花点时间弄清楚它是如何工作的。另一方面,如果您使用 for 循环来展
平相同的矩阵,那么您的代码将更加简单易读:
matrix = [
[0, 1, 0],
[1, 0, 1],
[2, 1, 2],
]
flat = []
for row in matrix:
for num in row:
flat.append(num)
print(flat)
输出:
[0, 1, 0, 1, 0, 1, 2, 1, 2]
现在,您可以看到代码一次遍历矩阵的一行,在移动到下一行之前取出该行中的所有元素。
虽然嵌套列表解析式可能看起来更具有 Python 风格,但对于能够编写出您的团队可以轻松理解和修改的代码来才是更加最重要的。当选择一个方法时,您应该根据解析式是有助于还是有损于可读性来做出相应的判断。
为大型数据集使用生成器
Python 中的列表解析式通过将整个列表存储到内存中来工作。对于小型至中型列表这通常很好。如果您想将前一千个整数相加,
那么列表解析式将轻松地解决此任务:
summary = sum([x for x in range(1000)])
print(summary)
输出:499500
但是,如果您需要对十亿个数字求和呢?您可以尝试执行此操作,但您的计算机可能不会有响应。这是可能因为计算机中分配大量内存。也许您是因为计算机没有如此多的内存资源。
例如,你想要一些第一个十亿整数,那么让我们使用生成器!这可能多需要一些时间,但计算机应该可以克服它:
summary = sum((x for x in range(1000000000)))
print(summary)
输出:
499999999500000000
让我们来对比一下哪种方法是更优的!
import timeit
def get_sum_with_map():
return sum(map(lambda x: x, range(1000000000)))
def get_sum_with_generator():
return sum((x for x in range(1000000000)))
print(timeit.timeit(get_sum_with_map, number=100))
print(timeit.timeit(get_sum_with_generator, number=100))
输出:
4940.844053814 # get_sum_with_map
3464.1995523349997 # get_sum_with_generator
正如您所见,生成器比 map() 高效得多。
总结
本文向您介绍了列表解析式,以及如何使用它来解决复杂的任务,而不会使您的代码变得过于困难。
现在你:
学习了几种创建列表的替代方法。
•找出每种方法的优点。
•可以简化循环和 map() 调用列表解析式。
•理解了一种将条件逻辑添加到解析式中的方法。
•可以创建集合和字典解析式。
•学会了何时不使用解析式。
今天分享的列表解析式学会了吗?文章特别长,看起来也很枯燥吧,不过能坚持到最后的一定都棒极了。
Python列表解析式的正确使用方式(二)的更多相关文章
- Python列表解析式的正确使用方式
先来逼逼两句: Python 是一种极其多样化和强大的编程语言!当需要解决一个问题时,它有着不同的方法.在本文中,将会展示列表解析式 (List Comprehension).我们将讨论如何使用它?什 ...
- Python列表解析式的正确使用方式(一)
先来逼逼两句: Python 是一种极其多样化和强大的编程语言!当需要解决一个问题时,它有着不同的方法.在本文中,将会展示列表解析式 (List Comprehension).我们将讨论如何使用它?什 ...
- python列表解析式,字典解析式,集合解析式和生成器
一.列表解析式(列表推倒式): 功能:是提供一种方便的列表创建方法,所以,列表解析式返回的是一个列表. 1 lst = [1, 3, 5, 8, 10] 2 ll = [x+x for x in ls ...
- [翻译]Python List Comprehensions: Explained Visually || Python列表解析式
原文1地址: http://treyhunner.com/2015/12/python-list-comprehensions-now-in-color/ 原文2地址: http://blog.tea ...
- Python - 列表解析式
列表解析——用来动态地创建列表 [expr for iter_var in iterable if cond_expr] 例子一: map(lambda x: x**2, range(6)) [0, ...
- [python] 列表解析式的高效与简洁
方法一(列表解析式): list1 = ["abc","efg","hij"] list2 = [i[0] for i in list1] ...
- Python 列表解析式竟然支持异步?
PEP原文:https://www.python.org/dev/peps/pep-0530 PEP标题:PEP 530 -- Asynchronous Comprehensions PEP作者:Yu ...
- Python - 列表解析式/生成器表达式
列表解析式: [expr for iter_var in iterable if cond_expr] 生成器表达式: (expr for iter_var in iterable if cond_e ...
- 以正确的方式开源 Python 项目
以正确的方式开源 Python 项目 大多数Python开发者至少都写过一个像工具.脚本.库或框架等对其他人也有用的工具.我写这篇文章的目的是让现有Python代码的开源过程尽可能清 晰和无痛.我不是 ...
随机推荐
- pt-osc又又出现死锁了
今天使用pt-osc修改mysql表结构,又出现死锁了,老大让尽量解决这个问题,我们先分析一下pt-osc容易出现死锁的原因,再来解决这个问题. 根据pt-osc打印的日志,可以看到pt-osc执行原 ...
- 论文翻译:2020_TinyLSTMs: Efficient Neural Speech Enhancement for Hearing Aids
论文地址:TinyLSTMs:助听器的高效神经语音增强 音频地址:https://github.com/Bose/efficient-neural-speech-enhancement 引用格式:Fe ...
- CA周记 - 带你进⼊ OpenAI 的世界
2021年11月的 Microsoft Ignite , 微软带来了全新的 Azure OpenAI Service,通过新的 Azure 认知服务能够访问 OpenAI 强大的 GPT-3 模型 . ...
- python学习-Day24
目录 今日内容详细 主菜 : ATM+购物车作业 项目开发流程 需求分析 架构设计 分组开发 项目测试 交付上线 需求分析 提炼项目功能 项目大致技术栈 架构设计 编程历经过程 三层架构 将ATM分为 ...
- Spring 源码(6)BeanFactoryPostProcessor怎么执行的?
上一篇文章 https://www.cnblogs.com/redwinter/p/16167214.html 解读了如何进行自定义属性值的编辑器的解析器,并且还介绍了BeanFactory的准备过程 ...
- 沁恒CH32V103C8T6开发环境笔记
CH32V103C8T6 CH32V103C8T6是沁恒的RISC-V内核MCU, 基于RISC-V3A处理器, 内核采用2级流水线处理,设置了静态分支预测.指令预取机制,支持DMA. 主要参数如下 ...
- wsgiref模块、web框架、django框架简介
"""web框架:将前端.数据库整合到一起的基于互联网传输的python代码 web框架也可以简单的理解为是软件开发架构里面的'服务端'""" ...
- flask配置文件、路由设置、模板语法、请求与响应、session使用、闪现功能(flash)
今日内容概要 flask 配置文件 flask 路由系统 flask模板语法 请求与相应 session 闪现(flash翻译过来的) 内容详细 1.flask 配置文件 # django ---&g ...
- 管家婆财贸ERP系列功能对比财贸c3-c8-c9功能对比介绍
管家婆财贸ERP系列功能对比财贸c3-c8-c9功能对比介绍 管家婆财贸ERP产品功能 序号 名称 说明 一 采购管理 对日常订货.入库.退货.估价入库等业务进行处理,多种方便灵活的订单定制方式,实现 ...
- 网络协议之:sctp流控制传输协议
目录 简介 TCP有什么不好 sctp的特点 总结 简介 要讲网络协议,肯定离不开OSI(Open System Interconnection)的七层模型. 我们一般关注的是网络层之上的几层,比如I ...