推导式(comprehension)
推导式是 python 的“语法糖”,用于简洁地构建容器。
推导式是一种独特的数据处理方式,它将一个可迭代对象(如列表、元组、集合、字符串等)的元素,通过某种运算或条件筛选后构建另一个新的数据序列的结构体。
python 支持各种数据结构的推导式
| 类型 | 语法 | 返回类型 |
|---|---|---|
| 列表推导式 | [expr for item in iterable] | list(立即求值,占内存) |
| 集合推导式 | {expr for item in iterable} | set |
| 字典推导式 | {k: v for k, v in iterable} | dict |
| 生成器表达式 | (expr for item in iterable) | generator(惰性求值) |
只有 圆括号 ( ) 的推导式 才是生成器。方括号 [ ] 是列表,花括号 { } 是集合或字典。
列表(list)推导式

my_list = [1, 2, 3, 4, 5, 6]
# 使用推导式,生成一个新的list带条件的列表推导式
condition_squares = [x for x in my_list if x % 2 == 0]
print(f"带条件的列表推导式:{condition_squares}") # [2, 4, 6]
# 列表推导式(立即计算)
squares_list = [x+3 for x in range(5) if x > 2]
print(squares_list)# [6, 7]
# 基础的列表推导式
basic_squares = (x**2 for x in range(5))
print(f"基础的列表推导式2:{tuple(basic_squares)}") # [0, 1, 4, 9, 16]
# 包含多个循环的列表推导式
continue1 = [1, 2, 3]
continue2 = ["a", "b", "c"]
tuple_list = [(i, j) for i in continue1 for j in continue2]
print(f"两个循环的列表推导式:{tuple_list}") # [(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'), (2, 'c'), (3, 'a'), (3, 'b'), (3, 'c')]元组(tuple)推导式
元组推导式和列表推导式的用法完全相同,只是元组推导式是用 () ,而列表推导式用的是 [],另外元组推导式返回的结果是一个生成器对象。
公式:

my_list = [1, 2, 3, 4, 5, 6]
# 使用推导式,生成一个新的tuple
condition_squares = (x for x in my_list if x % 2 == 0)
# 返回的是生成器对象 <generator object <genexpr> at 0x0000026a12285220>
print(condition_squares)
print(f"带条件的需要tuple()进行转换的推导式:{tuple(condition_squares)}")集合(set)推导式
公式:

my_list = [1,2,3,4,5,6]
# 使用推导式,生成一个新的tuple
condition_squares = {x for x in my_list if x % 2 == 0}
print(f"带条件的推导式:{condition_squares}")字典(dict)推导式

my_list = ['google','oracle', 'taobao','baidu']
#将列表中各字符串值为键,各字符串的长度为值,组成键值对
newdict = {key:len(key) for key in my_list}
print(f"f键值对推导式:{newdict}")迭代器(iterator)
是访问集合元素的一种方式,是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
在 python 中,对象只要实现了 __iter__() 和 __next__() 两个魔术方法,就是迭代器。
__iter__():返回自身(支持for循环)__next__():返回下一个元素,若无则抛出stopiteration
特点:
- 惰性求值:只在需要时计算下一个值
- 一次性:遍历完就“耗尽”,不能重复使用
- 省内存:不一次性加载所有数据
'''
迭代器
迭代是 python 最强大的功能之一,是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,迭代器只能往前不会后退,直到所有的元素被访问完结束。
迭代器有两个基本的方法:iter() 和 next()。
字符串,列表或元组对象都可用于创建迭代器:
'''
# 1 字符串,列表或元组对象都可用于创建迭代器:
my_list = [1, 2, 3, 4]
it = iter(my_list) # 创建迭代器对象
print (next(it)) # 输出迭代器的下一个元素
print (next(it))
# 如果再调用 next(it) 直到没数据,程序会报错 stopiteration
# 2 迭代器对象可以使用常规for语句进行遍历:
my_tuples = (1, 2, 3, 4)
my_iterator = iter(my_tuples) # 创建迭代器对象
for x in my_iterator:
print (x, end=" ")生成器(generator)
**生成器是最简单的创建 **迭代器** 的方式。生成器表达式 **是 推导式的一种,它返回的是 生成器(即迭代器),而不是列表!
在 python 中,使用了yield函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
当在生成器函数中使用 yield 语句时,函数的执行将会暂停,并将 yield 后面的表达式作为当前迭代的值返回。然后,每次调用生成器的 next() 方法或使用 for 循环进行迭代时,函数会从上次暂停的地方继续执行,直到再次遇到 yield 语句。这样,生成器函数可以逐步产生值,而不需要一次性计算并返回所有结果。调用一个生成器函数,返回的是一个迭代器对象。返回迭代器的函数,只能用于迭代操作。
工作原理:
当调用生成器函数时,它返回迭代器的函数但不立即执行;
每次调用next()时,执行到下一个yield语句;
yield返回一个值并暂停函数执行(保留所有局部状态);
再次调用next()时,执行到下一个yield语句就从从暂停处继续执行;
这样,生成器函数可以逐步产生值,而不需要一次性计算并返回所有结果。
案例代码
'''
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
当在生成器函数中使用 yield 语句时,函数的执行将会暂停,并将 yield 后面的表达式作为当前迭代的值返回。
然后,每次调用生成器的 next() 方法或使用 for 循环进行迭代时,函数会从上次暂停的地方继续执行,
直到再次遇到 yield 语句。这样,生成器函数可以逐步产生值,而不需要一次性计算并返回所有结果。
调用一个生成器函数,返回的是一个迭代器对象。
'''
def countdown(n):
"""
countdown 函数是一个生成器函数。它使用 yield 语句逐步产生从 n 到 1 的倒数数字。
在每次调用 yield 语句时,函数会返回当前的倒数值,并在下一次调用时从上次暂停的地方继续执行。
通过创建生成器对象并使用 next() 函数或 for 循环迭代生成器,我们可以逐步获取生成器函数产生的值。
在这个例子中,我们首先使用 next() 函数获取前三个倒数值,然后通过 for 循环获取剩下的两个倒数值。
生成器函数的优势是它们可以按需生成值,避免一次性生成大量数据并占用大量内存。
:param n:
:return:
"""
while n > 0:
yield n
n -= 1
# 创建生成器对象
generator = countdown(5)
print(type(generator))
# 通过迭代生成器获取值
print(next(generator)) # 输出: 5
print(next(generator)) # 输出: 4
print(next(generator)) # 输出: 3
# 使用 for 循环迭代生成器
for value in generator:
print(value) # 输出: 2 1
# 生成器表达式(generator expression)
gen = (x * 2 for x in range(3))
print(type(gen)) # <class 'generator'>
print(list(gen)) # [0, 2, 4]推导式和生成器区别

案例代码
'''
推导式(comprehension) vs 生成器(generator)
'''
# 1 基本用法
# 列表推导式 - 立即创建完整列表
list_comp = [x * 2 for x in range(5)]
print("列表推导式:", list_comp) # [0, 2, 4, 6, 8]
print("类型:", type(list_comp)) # <class 'list'>
# 元组推导式(生成器表达式),先生成器表达式 - 创建生成器对象
gen_expr = (x * 2 for x in range(5))
print("生成器表达式:", gen_expr) # <generator object <genexpr> at 0x...>
# 生成器(generator)是一个返回迭代器(iterator)的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
print(next(gen_expr))
print(next(gen_expr))
print(next(gen_expr))
print(next(gen_expr))
print(next(gen_expr))
# print(next(gen_expr)) # 超过了下表会如何?stopiteration
print("类型:", type(gen_expr)) # <class 'generator'>
print("元组推导式(生成器表达式):", tuple(gen_expr)) # (0, 2, 4, 6, 8) 如果前面next()迭代过了为空
print()
print()
# 2 内存占用对比
import sys
const_1w = 10000
# 列表推导式 - 占用较多内存
large_list = [x for x in range(100 * const_1w)]
print("列表内存占用:", sys.getsizeof(large_list), "bytes") # 约 8-9mb
# 元组推导式(生成器表达式) - 占用很少内存
large_gen = (x for x in range(100 * const_1w))
print("生成器内存占用:", sys.getsizeof(large_gen), "bytes") # 约 100-200 bytes
print()
print()
# 3 执行时机对比
def expensive_operation(x):
print(f"计算 {x} 的平方...")
return x * x
print("=== 列表推导式(立即执行)===")
squares_list = [expensive_operation(x) for x in range(3)]
# 会立即打印所有"计算..."消息
print("=== 元组推导式(生成器表达式)(惰性执行)===")
squares_gen = (expensive_operation(x) for x in range(3))
# 此时不会打印任何东西
print("元组推导式(生成器表达式):")
print(next(squares_gen))
print(next(squares_gen))
print(next(squares_gen))
for result in squares_gen:
print("----->结果:", result)
#只有在迭代时才会执行计算
# 4 可重用性对比
# 列表推导式 - 可重用
numbers_list = [1, 2, 3, 4, 5]
squared_list = [x*x for x in numbers_list]
print("列表推导式第一次遍历:")
for num in squared_list:
print(num) # 1, 4, 9, 16, 25
print("列表推导式第二次遍历:")
for num in squared_list:
print(num) # 可以再次遍历
# 生成器表达式 - 通常一次性
squared_gen = (x*x for x in numbers_list)
print("元组推导式(生成器表达式)第一次遍历:")
for num in squared_gen:
print(num) # 1, 4, 9, 16, 25
print("元组推导式(生成器表达式)第二次遍历:")
for num in squared_gen:
print(num) # 不会输出任何内容(生成器已耗尽)可迭代对象(iterable)迭代器(iterator)的区别:
| ** 特性 ** | ** 可迭代对象(iterable) ** | ** 迭代器(iterator) ** |
|---|---|---|
| 定义 | 实现了 __iter__()方法的对象 | 实现了 __iter__()和 __next__()方法的对象 |
| 功能 | 可以被迭代 | 可以记住迭代状态并产生下一个值 |
| 内存使用 | 通常需要更多内存 | 惰性计算,节省内存 |
| 数据消耗 | 可以多次迭代 | 通常只能迭代一次 |
| 示例 | 列表、元组、字典、字符串 | 文件对象、生成器 |
到此这篇关于python高级语法之推导式+迭代器+生成器案例代码的文章就介绍到这了,更多相关python推导式、迭代器、生成器内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论