Python生成器与推导式核心机制解析
本文深入解析Python中生成器的本质及其两种构建方式:生成器函数与生成器表达式。详细对比yield与return的执行逻辑,阐述生成器在内存占用上的优势。同时介绍列表推导式的循环与筛选模式,以及生成器表达式的简洁用法,帮助开发者掌握高效的数据处理技巧。
生成器的基本概念
生成器本质上是用户通过Python代码自定义实现的迭代器,其核心行为与迭代器完全一致。
在Python中,构建生成器主要依赖于以下两种途径:
第一种方式是通过定义生成器函数来实现。
第二种方式则是利用生成器表达式。
生成器函数的实现与机制
关于生成器函数的具体实现:
普通函数
def func1(x):
x += 1
return x
print(func1(5))
生成器函数
def func1(x):
x += 1
yield x
g_obj = func1(5)
print(g_obj.__next__())
在生成器运行过程中,每一次调用next()方法都会对应执行到一个yield语句。
yield关键字与return关键字存在显著差异。
return语句用于终止函数的执行,并将结果值返回给函数的调用者。
yield语句不会导致函数终止,而是挂起当前状态;每次调用next()或__next__()时,生成器对象会返回yield后的值。
生成器函数与普通迭代器对象之间存在以下区别:
区别之一在于定制化的灵活性:
l1 = [1,2,3,4,5]
l1.__iter__()
def func1(x):
x += 1
yield x
x += 3
yield x
x += 5
yield x
g1 = func1(5)
print(g1.__next__())
print(g1.__next__())
print(g1.__next__())
区别之二体现在内存使用的层级上。
普通迭代器通常需要将可迭代对象先转换为列表等结构,这在数据量大时会占用大量内存。
生成器则是按需生成数据,无需预先转换整个数据集,从机制上大幅节省了内存空间。
send与next方法的使用
关于send()与next()方法的交互:
send()方法与next()类似,都是用于获取生成器中yield语句的值(即执行到一个yield点)。
send()方法可以向当前挂起的yield处传入一个值,但首次启动生成器时,必须使用next()方法。
需要注意的是,生成器中最后一个yield语句无法接收到通过send()传入的值。
列表推导式详解
列表推导式允许用一行代码构建所需的列表。
其基本循环模式语法为:[加工后的变量 for 变量 in 可迭代对象]。
lis = [i for i in range(1,101)]
print(lis)
lis = ['骑士计划%s期'% i for i in range(1,16)]
print(lis)
lis = [i**2 for i in range(1,11)]
print(lis)
print([i for i in range(1,31) if i % 3 == 0])
print([i*i for i in range(1,31) if i % 3 is 0 ])
列表推导式还支持筛选模式。
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
print([q for name in names for q in name if q.count('e') >= 2])
列表推导式
其优点在于代码简洁,一行即可解决复杂列表生成问题。
缺点包括代码可读性随复杂度增加而降低,调试困难,且不建议嵌套超过三层循环。
列表推导式并非适用于所有场景,应根据实际需求决定是否使用,无需刻意滥用。
生成器表达式
生成器表达式只需将列表推导式中的方括号[]替换为圆括号()即可。
g = (i for i in range(199))
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
以上内容涵盖了Python生成器与推导式的主要知识点,希望对读者的学习有所帮助,欢迎继续支持本站获取更多技术资源。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









