Python-推导式、生成器、迭代器

列表推导式

最终得到的是一个列表。

格式1:[i for i in 可迭代的]

格式2:[i for i in 可迭代的 if 条件]        #for循环后,如果满足条件则放入列表

格式3:[结果1 if 条件 else 结果2 for 变量 in 可迭代的]        #可读性比较差

格式4:[(i,j) for i in 可循环的 for j in 可循环的]        #嵌套for循环

将1-20的数字放入列表

# 方法一:自己写一个列表
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
print(list1)

# 方法二:for循环
list2 = []
for i in range(1, 21):
    list2.append(i)
print(list2)

# 方法三:列表推导式
list3 = [i for i in range(1, 21)]
print(list3)

---------------
输出:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

将1-50的偶数存入列表

list4 = [i for i in range(0, 51) if i % 2 == 0]
print(list4)

---------
输出:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50]

集合推导式

集合推导式。格式就是将列表推导式的[]换成{}

set1 = {i for i in range(5)}
print(set1)

-------------
输出:
{0, 1, 2, 3, 4}

字典推导式

dict1 = {'a': 1, 'b': 2, 'c': 3}
new_dict = {key: value + 1 for key, value in dict1.items()}
print(new_dict)

--------------
输出:
{'a': 2, 'b': 3, 'c': 4}

生成器-generator

通过前面的列表生成器,可以生成一个很大的列表。但是同时当元素非常多的时候,也会很占空间。

所以说,元素可以按某种算法推算出来,就可以不用占用那么多空间了。Python中这种机制,就叫做生成器generator。

格式一-把列表推导式的[]换成()

generator1 = (x * x for x in range(5))

可以用next()获取generator中的下一个值。但是如果没有值了,还调用了next(),则会报错StopIteration

generator1 = (x * x for x in range(5))
print(next(generator1))
print(next(generator1))
print(next(generator1))
print(next(generator1))
print(next(generator1))

-------------
输出:
0
1
4
9
16

生成器generator也是可迭代对象,可以直接可以用for循环输出,也不用考虑StopIteration报错。

generator1 = (x * x for x in range(5))
for i in generator1:
    print(i)

格式二-yield

有些复杂的数列,生成器不太好写出来,但是用函数比较容易写出来。就可以结合yield将函数编程一个generator。

比如用函数生成斐波那契额数列。用函数可以方便地写出来,但是用生成器不太好写。

def fib(max):
    n,a,b = 0,0,1
    while n<max:
        print(b)
        a,b = b,a+b
        n +=1
    return 'end'

fib(8)

-------------------
输出:
1
1
2
3
5
8
13
21

只要用yield替换print的部分,就可以将函数变成一个generator

def fib(max):
    n,a,b = 0,0,1
    while n<max:
        yield b
        a,b = b,a+b
        n +=1
    return 'end'

g = fib(8)
print('g的类型',type(g))

for i in g:
    print(i)

-----------
输出:
g的类型 <class 'generator'>
1
1
2
3
5
8
13
21

而且“函数”中有return的时候,必须要用expect捕获异常,return的值会以StopIteration错误类型的值的形式打印出来。

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n += 1
    return 'end'


g = fib(5)

while True:
    try:
        print(next(g))
    except StopIteration as err:
        print('StopIteration:',err)
        break

-------------
输出:
1
1
2
3
5
StopIteration: end

关于yield备注:

  1. 当函数中有yield的时候,函数就从普通函数,进化成了generator
  2. 函数的执行流程会发生变化。函数执行时,每次迭代的时候到了yield处就会停止。下一次迭代会从上次停止的yield处继续执行。

用一个更简单的例子演示一下yield的执行过程。

可以看到下面的函数,每次next()时,都是到yield结束;下次yield的时候又从上次结束的地方开始。

def func():
    print('step 1')
    yield 'a'
    print('step 2')
    yield 'b'
    print('step 3')
    yield 'c'

g = func()
print(next(g))
print('-------------->')
print(next(g))
print('-------------->')
print(next(g))

-------------
输出:
step 1
a
-------------->
step 2
b
-------------->
step 3
c

func()会新建一个generator。所以以下示例三次next()每次都会新建独立的generator对象。所以每次都只输出到第一次yield出现的地方。

def func():
    print('step 1')
    yield 'a'
    print('step 2')
    yield 'b'
    print('step 3')
    yield 'c'

print(next(func()))
print(next(func()))
print(next(func()))

------------
输出:
step 1
a
step 1
a
step 1
a

迭代器

可迭代的-Iterable

可被for循环的对象,就是可迭代的。其分为两类:

  • 一类是集合数据,如:list、tuple、set、dict、str
  • 一类是生成器generator和带yield的generator function

可以使用isinstance()判断一个对象是否是Iterable(可迭代的)。

from collections import Iterable

print(isinstance('abc', Iterable))
print(isinstance([], Iterable))
print(isinstance({}, Iterable))
print(isinstance((), Iterable))
print(isinstance((x for x in range(5)), Iterable))
print(isinstance(99, Iterable))

----------
输出:
True
True
True
True
True
False

 

迭代器-Iterator

可以被next()调用并不断返回下一个值的对象,称为迭代器:Iterator。

from collections import Iterator

print(isinstance('abc', Iterator))
print(isinstance([], Iterator))
print(isinstance({}, Iterator))
print(isinstance((), Iterator))
print(isinstance((x for x in range(5)), Iterator))

-----------------
输出:
False
False
False
False
True

Iterable转换Iterator

可以使用iter(),将可迭代的对象转换成迭代器。

from collections import Iterator

print(isinstance(iter('abc'), Iterator))
print(isinstance(iter([]), Iterator))
print(isinstance(iter({}), Iterator))
print(isinstance(iter(()), Iterator))
print(isinstance((x for x in range(5)), Iterator))

------------
输出:
True
True
True
True
True

总结

  1. 不是所有可迭代的对象(Iterable)都是生成器(Iterator)
  2. 所有生成器(Iterator),都是可迭代的对象(Iterable)
  3. 可以使用iter(),将可迭代的对象转换为生成器
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值