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代码的开源过程尽可能清 晰和无痛.我不是 ...
随机推荐
- 【2021 ICPC Asia Jinan 区域赛】 C Optimal Strategy推公式-组合数-逆元快速幂
题目链接 题目详情 (pintia.cn) 题目 题意 有n个物品在他们面前,编号从1自n.两人轮流移走物品.在移动中,玩家选择未被拿走的物品并将其拿走.当所有物品被拿走时,游戏就结束了.任何一个玩家 ...
- 2021-01-25 cf #697 Div3 C题(超时,换思路减少复杂度)
题目链接:https://codeforces.com/contest/1475/problem/C 题意要求:需组成的2对,男的序号不能重,女的序号不能重 比如这例 输入: 行1--测试个数 行1` ...
- unity 编辑器扩展简单入门
unity 编辑器扩展简单入门 通过使用编辑器扩展,我们可以对一些机械的操作实现自动化,而不用使用额外的环境,将工具与开发环境融为一体:并且,编辑器扩展也提供GUI库,来实现可视化操作:编辑器扩展甚至 ...
- 前端性能优化之js,css调用优化
规则1:减少HTTP请求 把多个JS请求合并为一个JS请求,把多个CSS请求合并为一个CSS请求.从而减少从客户端向服务器端的请求数. 规则3:添加Expires头 用http ...
- Java语言学习day10--7月9日
###09方法的重载 * A: 方法的重载 * 在同一个类中,方法名相同,参数列表不同.与返回值类型无关. * 参数列表不同: * A:参数个数不同 * B:参数类型不同 * C:参数的顺序不同(算重 ...
- Dockerfile 命令详解及最佳实践
Dockerfile 命令详解 FROM 指定基础镜像(必选) 所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制.就像我们之前运行了一个 nginx 镜像的容器,再进行修改一样,基础镜像是必须指 ...
- 解决windows下WslRegisterDistribution failed with error: 0x80070050的问题
最近升级了老电脑的windows10的系统,发现wsl2里面安装的ubuntu20.04不能在windows terminal正常启动了(我之前是把ubuntu20.04作为默认启动终端的.) 涉及报 ...
- js 如何判断变量类型
自定义一些类型 const boolean = true const string = '这是一个字符串' const number = 1 const array = [] const object ...
- HTML5 Canvas 超逼真烟花绽放动画
各位前端朋友们,大家好!五一假期即将结束,在开启加班模式之前,我要给大家分享一个超酷超逼真的HTML5 Canvas烟花模拟动画.这次升级版的烟花动画有以下几个特点: 烟花绽放时,将展现不同的色彩,不 ...
- 【Azure Developer】使用 Microsoft Authentication Libraries (MSAL) 如何来获取Token呢 (通过用户名和密码方式获取Access Token)
问题描述 在上一篇博文<[Azure Developer]使用 adal4j(Azure Active Directory authentication library for Java)如何来 ...