[Python]迭代器生成器 随手记

同步与异步

# 同步:指的是一个顺序,排队,表现:等待and阻塞;
# 异步:不讲究是否顺序,不排队,表现:不等待and不阻塞

迭代器

定义:iterator,实现迭代器协议的对象;
迭代器协议:__iter__ __next__
魔术方法代表协议,与java中interface类似

实例

通过迭代器实现生成指定位置的斐波那契数

斐波那契数列(兔子数列、黄金分割数列[(n-1)/n=0.618])
1,2,3,5,8,13,21,…

code

class FibNums:
    def __init__(self, num):
        self.a, self.b = 0, 1
        self.count = 0
        self.num = num

    def __iter__(self):
        return self

    def __next__(self):
        if self.count < self.num:
            self.a, self.b = self.b, self.a + self.b
            self.count += 1
            return self.a
        raise StopIteration("")

测试

实例化

查看下实例化后的类型:

fib_num = FibNums(5)
# 查看类型
print(fib_num)  # <__main__.FibNums object at 0x000000000298BF60>
print(type(fib_num)) # <class '__main__.FibNums'>
取值
方法一:通过next()取值

# 方法一:通过next()取值
print(next(fib_num))  # 1
print(next(fib_num))  # 1
print(next(fib_num))  # 2

打印结果

<__main__.FibNums object at 0x000000000298BF60>
<class '__main__.FibNums'>
1
1
2
方法二:for in
for i in fib_num:
    print(i)

打印结果

1
1
2
3
5

生成器


生成器
-  就是迭代器语法简化的升级版
-  标志:yield

普通方法实现斐波那契

# 普通函数
def fib(num):
    a, b = 0, 1
    for _ in range(num):
        a, b = b, a + b
    return a

验证

res_19 = fib(19)
res_20 = fib(20)
print(res_19)
print(res_20)

结果

4181
6765

生成器实现

def fib2(num):
    a, b = 0, 1
    for _ in range(num):
        a, b = b, a + b
        yield a

验证

调用函数不是简单的获得返回值,而是创建生成器对象

res2_19 = fib2(19)
print(type(res2_19))
print(res2_19)

结果

<class 'generator'>
<generator object fib2 at 0x0000000009F5E6D8>

取值

方法一:

print(next(res2_19))  # 1
print(next(res2_19))  # 1
print(next(res2_19))  # 2

方法二:

for i in res2_19:
    print(i)

结果

1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181

生成器创建

常见的有两种方法创建:

# 方法一:yield关键字的函数;
# 方法二:生成器表达式;

方法一:yield关键字的函数

def gen_a():
    for i in range(1, 100, 2):
        yield i

查看类型

print(gen_a())  # <generator object gen_a at 0x0000000009F5F9A8>
print(type(gen_a()))  # <class 'generator'>

这种方式有一个简化版本

# 简化版本:
def gen_a2():
    yield from range(1, 100, 2)

这里不做结果验证,从代码形式上看优于第一种方式,根据自己的需要,选择~~~

方法二:生成器表达式

表示方法:使用();

gen_b = (num for num in range(1, 100, 2))
print(gen_b)  # <generator object <genexpr> at 0x0000000009F5F9A8>
print(type(gen_b))  # <class 'generator'>

取值

和之前一样,再啰嗦两句:
方法一:

print(next(gen_b))
print(next(gen_b))
print(next(gen_b))

方法二

for i in gen_b:
    print(i)

补充

可迭代对象

列表,集合,字符串不叫迭代器,叫可迭代对象

l_test = [1, 2, 3, 4, 5, 6]
# print(next(l_test))  # TypeError: 'list' object is not an iterator
# 由上可以看出,列表不是迭代器,可以通过内置函数iter()将可迭代对象转换成iterator
l_iterator = iter(l_test)
print(type(l_iterator))

print(next(l_iterator))
print(next(l_iterator))
for i in l_iterator:
    print(i)

打印结果

<class 'list_iterator'>
1
2
3
4
5
6

生成式

又称:推导式,解析式;
常见的有列表,字典,集合,生成器4类,都有其对应的生成式;
注意
元祖没有生成式、推导式
优势

  • 代码格式简短且漂亮;
  • 在数据量大的时候性能优于传统方式;
# 列表生成式(使用:[])
[num for num in range(1,100,2)] 
# 集合生成式(注意:集合是一个无序不重复元素集;使用:{})
{num for num in range(1,100,2)} 
# 字典推导式(同时取出键和值,中间用冒号分开;使用:{})
{num:num**2 for num in range(1,100,2)} 
# 元祖没有生成式、推导式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔都吴所谓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值