python 表达式解析,列表表达式 python
Python是一种极其多样化和强大的编程语言!当一个问题需要解决时,它有不同的方法。本文将展示如何使用列表解析表达式,有需要的可以参考。
00-1010 List解析表达式的优点如何在Python中创建List Loop map()对象List解析表达式哪种方法更有效高级解析表达式条件逻辑设置解析表达式字典解析Walrus运算符什么时候不要使用解析表达式注意嵌套解析表达式使用生成器对大型数据集进行汇总Python是一种极其多样且功能强大的编程语言!当一个问题需要解决时,它有不同的方法。
在这篇文章中,列表解析式(List Comprehension)将被展示。我们将讨论如何使用它。什么时候该用,什么时候不该用?
目录
比回收更节省时间和空间。需要更少的代码行。迭代语句可以转换成公式。
列表解析式的优势
分析公式是一种基于现有列表创建列表的语法结构。让我们看看创建列表的不同实现。
如何在 Python 中创建列表
是通过循环创建列表的传统方式。不管你用什么样的周期。要以这种方式创建列表,您应该:
1.实例化一个空列表。
2.循环遍历迭代(如range)元素。
3.将每个元素附加到列表的末尾。
数字=[]
对于(10):范围内的数字
numbers.append(数字)
打印(数字)
输出:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
在这个例子中,你实例化了一个空的列表编号。然后使用for循环遍历range(10 ),并使用append()方法将每个数字追加到列表的末尾。
循环
Map()是创建列表的另一种方式。您需要向map()传递一个函数和一个iterable对象,之后它将创建一个对象。该对象包含通过使用指定函数执行每个迭代元素获得的输出。
例如,我们将提出在某些产品的价格中增加增值税的任务。
增值税百分比=0.1 # 10%
定义附加增值税(价格):
退货价格(价格*增值税百分比)
价格=[10.03,8.6,32.85,41.5,22.64]
grand_prices=map(add_vat,价格)
打印(大价格)
grand_prices=list(grand_prices)
打印(大价格)
您已经构建了add_vat()函数并创建了prices iterable对象。您将这两个参数传递给map()并收集生成的map对象grand_prices,或者您可以使用list()轻松地将其转换成一个列表。
输出:
0x7f18721e7400 #地图上的地图对象(附加增值税,价格)
[11.03,9.46,36.14,45.65,24.9] # list(grand_prices)
map() 对象
现在,我们来看看列表分析法!这是真正的Python风格,是创建列表的更好方式。为了了解这种方法有多强大,我们使用
一个单行代码来重写那个循环示例。
numbers = [number for number in range(10)]print(numbers)
输出
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
正如您所见,这是一种不可思议的方法!列表解析式看起来足够可读,您不需要编写更多代码,而只需一行。
为了更好地理解列表,请查看以下语法格式:
new_list = [expression for member in iterable]
哪种方法更有效
好的,我们已经学习了如何使用循环、map() 和列表解析式来创建列表,在您的脑海中可能会提出哪种方法更有效的问题。我们来分析一下吧!
import randomimport timeit
VAT_PERCENT = 0.1
PRICES = [random.randrange(100) for x in range(100000)]
def add_vat(price):
return price + (price * VAT_PERCENT)
def get_grand_prices_with_map():
return list(map(add_vat, PRICES))
def get_grand_prices_with_comprehension():
return [add_vat(price) for price in PRICES]
def get_grand_prices_with_loop():
grand_prices = []
for price in PRICES:
grand_prices.append(add_vat(price))
return grand_prices
print(timeit.timeit(get_grand_prices_with_map, number=100))
print(timeit.timeit(add_grand_prices_with_comprehension, number=100))
print(timeit.timeit(get_grand_prices_with_loop, number=100))
输出:
0.9833468980004909 # with_map
1.197223742999995 # with_comprehension
1.3564663889992516 # with_loop
正如我们现在所看到的,创建列表的最优的方法是 map(),排在第二位的是列表解析式,最后是循环。
但是,方法的选择应取决于您想要实现的目标。
- 使用 map() 可以使你的代码更高效。
- 使用循环可以使代码的思路展现更加清晰。
- 使用列表解析式可以您使代码更加紧凑,且较高效。这是创建列表的最佳方式,因为这种方式可读性最强。
高级解析式
条件逻辑
早些时候,我向您展示了这个公式:
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 randomdef 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 timeitdef 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列表解析式内容请搜索盛行IT软件开发工作室以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT软件开发工作室!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。