近几天学习到Python的函数编程进阶板块,对于列表生成式,生成器,迭代器的学习直接懵逼,在经过一番实例演习之后初见端倪,在此将收获的干货分享给大家##希望大家点赞收藏,多多鼓励原创学习!!!
1. 列表生成式
- 定义:类似于三元运算,原理都是一样的,将后面for循环遍历出的数值赋值给变量存入列表当中进行一个列表的生成与赋值,(可以简化代码)。
- 举例:
numbers = [i for i in range(100) if i % 2 == 0]
print("输出:",numbers)
输出结果如下:
输出: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
个人认为,列表生成式相当于以下函数的简写,Python为我们提供了一个较为简单的语法。
numbers = []
for i in range(20):
if i % 2 == 0:
numbers.append(i)
print(numbers)
- 进阶举例:对于字符串列表或者算法生成式也是一样的,见一下代码:
(1)遍历字符串添加if判断
list = ["dsaf","asfa","jytrnhtd","weqrdsg","qnerox","owiajnd","iuhgwdf"]
list2 = [i for i in list if "a" in i]
print(list2)
结果为:
['dsaf', 'asfa', 'owiajnd']
(2)变量为表达式形式
list3 = [i*ii-1 for i in range(5) for ii in range(5) if ii%2 == 0]
print(list3)
结果为:
[-1, -1, -1, -1, 1, 3, -1, 3, 7, -1, 5, 11, -1, 7, 15]
2. 列表生成器 ~generator
- 定义:并没有明确定义,类似于列表生成式,只不过将外围的[ ]换成了( ),在创建列表生成器的瞬间并不会产生数值,只是创建了生成器在内存中的存储地址,只有经过next()调用后或者yield返回值的时候才会生成数值。相比于range()函数来说节省了内存空间,不会一次性生成大量数值,在大数据处理或者网络数据传输过程中具有很大的应用意义,使用生成器的时候也是循环遍历。
- 举例:定义一个列表生成器赋值给a,通过next方法输出生成器产生的每个数值,next调用一次只能生成一个数值并停止在原处,类似于yield方法(后面会讲),如果直接打印的话会返回生成器的存储地址。
a = (x for x in range(10) if x%3 == 1)#先创建了列表生成器 还没有生成值
print(a)
print(next(a))
print(next(a))
print(next(a))
print(list(a))
结果为:
<generator object <genexpr> at 0x00000252F78A9D60>
1
4
7
[]
最后打印的空字符的原因是生成器的生成顺序是只前进不后退,当调用三次next方法后生成器已经遍历完全,再次打印就会空值,如果先打印的话就会全部打印,如下:
a = (x for x in range(10) if x%3 == 1)#先创建了列表生成器 还没有生成值
print(list(a))
结果为:[1, 4, 7]
- 使用生成器实现斐波那契数列
在进行两值互换时使用a,b=b,a的方法快速进行两值互换,注释中也提到了传统存值方法,码友自行选择。**对于多行的print函数使用,解释一下,**这是因为使用生成器yield方法,相当于暂停功能,一次next会使得yield向前遍历一次之后停止,如果需要继续求值的话需要再次遍历,所以使用多次print函数
#生成器实现
def cal(n):
a = 1
b = 1
count = 0
print(a,end=" ")
while count < n-1:
yield b#此时已经是一个生成器 需要保存返回值 生成器返回的是yield后面的值
a,b = b,a+b#Python方式 两值互换 也可以存新值
"""
tem = a
a = b
b = tem + b
"""
count += 1
g = cal(10)
print(next(g),end=" ")
print(next(g),end=" ")
print(next(g),end=" ")
print(next(g),end=" ")
print(next(g),end=" ")
print(next(g),end=" ")
print(next(g),end=" ")
print(next(g),end=" ")
print(next(g),end=" ")
输出结果为:
1 1 2 3 5 8 13 21 34 55
以上代码可称之为函数生成器,只是通过yield关键字就直接讲cal函数转换为生成器,打印cal的话会打印其的存储地址。稍加改动即可变为传统方法实现斐波那契数列。代码如下:
#使用while循环实现
def cal(n):
a = 1
b = 1
count = 0
print(a,end=" ")
while count < n-1:
print(b,end=' ')
a,b = b,a+b#Python方式 两值互换 也可以存新值
"""
tem = a
a = b
b = tem + b
"""
count += 1
cal(10)
该部分请读者自行复制实现。
- 进阶举例: 除了使用yield关键字向外部传递值以外,python也提供了向内传递数值的方法,send()函数,具体应用参照如下代码,实现一个函数接受外部传递进来的数值:
def g_test():
while 1:
n = yield #将收到的值传给生成器
print("从外部收到的值为:",n)
# n = yield
# print("从外部收到的值为:",n)
g = g_test()
g.__next__()#调用生成器同时传递None值给生成器
for i in range(10):
g.send(i)#调用生成器传递i
结果如下:实现send里的值反馈给yield赋值给n。反向传值。
从外部收到的值为: 0
从外部收到的值为: 1
从外部收到的值为: 2
从外部收到的值为: 3
从外部收到的值为: 4
从外部收到的值为: 5
从外部收到的值为: 6
从外部收到的值为: 7
从外部收到的值为: 8
从外部收到的值为: 9
注意,注释部分代码必须嵌套进死循环里,这里循环受yield控制,如果无循环的话则生成器生成初始传值None后便不再调用生成器,输出为第一次传递的值便报错,如下:
从外部收到的值为: 0
Traceback (most recent call last):
File "D:\桌面\Python\Excise\qusetions1000_excise.py", line 495, in <module>
g.send(i)#调用生成器传递i
StopIteration
3. 迭代器 ~iterable
- 定义:迭代器是一个可迭代的对象,即可遍历可循环,如字符串,列表,字典,集合。可通过iter()函数创建迭代器对象,这是访问集合的方式之一,类似于生成器。
- 实例:
list = [1,2,3,4,"hdskauf"]
it = iter(list)
print(it)
print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))
结果为:
<list_iterator object at 0x000001EB80FF3F10>
1
2
3
4
hdskauf
这里首先创建了迭代器list,访问其内存地址通过打印其指向变量即可,通过next方法同样可以单次取值,也可以使用循环遍历内容,同生成器部分,请大家仿照练习,代码如下。
list = [1,2,3,4,"hdskauf"]
it = iter(list)
print(it)
for i in it:
print(i,end=" ")
结果为:
<list_iterator object at 0x0000022D78453F10>
1 2 3 4 hdskauf
总结一下,迭代器,生成器,列表生成式属于Python进阶内容,搞懂的话需要一些时间,想学习的小伙伴不要心急,慢慢来。
感谢大家的阅读。