Python 是一种极其多样化和强大的编程语言!当需要解决一个问题时,它有着不同的方法。在本文中,将会展示列表解析式(List Comprehension)。我们将讨论如何使用它?什么时候该或不该使用它?
列表解析式的优势
·比循环更节省时间和空间。
· 需要更少的代码行。
· 可将迭代语句转换为公式。
如何在Python中创建列表
列表解析式是一种基于现有列表创建列表的语法结构。让我们来看看创建列表的不同实现
循环
循环是创建列表的传统方式。不管你使用什么样的循环。要以这种方式创建列表,您应该:
1. 实例化一个空列表。
2. 循环遍历一个可迭代的(如range)的元素。
3. 将每个元素附加到列表的末尾。
numbers = []
for number in range(10):
numbers.append(number)
print(numbers)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
在此示例中,您实例化了一个空列表 numbers?。然后使用 for? 循环迭代 range(10)? 并使用 append() 方法将每个数字附加到列表的末尾。
map() 对象
map()是创建列表的另一种方法。您需要向 map() 传递一个函数和一个可迭代对象,之后它会创建一个对象。该对象包含使用指定函数执行每个迭代元素所获得的输出。
例如,我们将呈现在某些产品的价格中增加增值税的任务。
VAT_PERCENT = 0.1 # 10%
def add_vat(price):
return price + (price * VAT_PERCENT)
prices = [10.03, 8.6, 32.85, 41.5, 22.64]
grand_prices = map(add_vat, prices)
print(grand_prices)
grand_prices = list(grand_prices)
print(grand_prices)
您已经构建了 add_vat()? 函数并创建了 prices? 可迭代对象。您将这两个参数都传递给 map()? 并收集生成的 map? 对象 grand_prices?,或者您可以使用 list() 轻松地将其转换为列表。
<map object at 0x7f18721e7400> # map(add_vat, prices)
[11.03, 9.46, 36.14, 45.65, 24.9] # list(grand_prices)
列表解析式
现在,让我们看一下列表解析式方法!这确实是 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 random
import 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]