python学习第十三天 迭代器 生成器

Posted xubohua

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python学习第十三天 迭代器 生成器相关的知识,希望对你有一定的参考价值。

1.函数复习总结

技术分享图片
# 函数 —— 2天
    # 函数的定义和调用
    # def 函数名(形参):
        #函数体
        #return 返回值
    #调用 函数名(实参)
    # 站在形参的角度上 : 位置参数,*args,默认参数(陷阱),**kwargs
    # 站在实参的角度上 : 按照位置传,按照关键字传
    # 返回值:没有返回值 返回一个值 返回多个值
    # 接收返回值:没有返回值不接收,返回一个值用一个变量接收,返回多个值用一个变量或者对应数目的变量接收
# 闭包函数 —— 在内部函数引用外部函数的变量
# 装饰器函数—— 装饰器一定是闭包函数
    # 装饰器的作用 : 在不改变原来函数的调用方式的情况下 在这个函数的前后添加新的功能
    # 完美的符合了一个开发原则 :开放封闭原则
        # 对扩展是开发的
        # 对修改是封闭的
    # 基础的装饰器
        # from functools import wraps
        # def wrapper(func):
        #     @wraps(func)
        #     def inner(*args,**kwargs):
        #          ‘‘‘在函数被调用之前添加的代码‘‘‘
        #         ret = func(*args,**kwargs)   # func是被装饰的函数 在这里被调用
        #         ‘‘‘在函数被调用之后添加的代码‘‘‘
        #         return ret
        #     return inner
        # 使用 —— @wrapper
        # @wrapper
        # def func():   #inner
        #     pass
        #
        # func.__name__
    # 带参数的装饰器
        # @wrapper -- > @warapper(argument)
        # 三层嵌套函数
        # def outer(形参):
        #     def wrapper(func):
        #         def inner(*args,**kwargs):
        #             ‘‘‘在函数被调用之前添加的代码‘‘‘
        #             ret = func(*args,**kwargs)   # func是被装饰的函数 在这里被调用
        #             ‘‘‘在函数被调用之后添加的代码‘‘‘
        #             return ret
        #         return inner
        #     return wrapper
        # @outer(True)
        # def func():
        #     pass
    # 多个装饰器装饰一个函数
        # 俄罗斯套娃

    #def wrapper1(func):
        #     @wraps(func)
        #     def inner(*args,**kwargs):
        #         print(‘before 1‘)
        #         print(‘******‘)
        #         ret = func(*args,**kwargs)   # func是被装饰的函数 在这里被调用
        #         ‘‘‘在函数被调用之后添加的代码‘‘‘
        #         return ret
    # def wrapper2(func):
    #     @wraps(func)
    #     def inner(*args,**kwargs):
    #         print(‘before 2‘)
    #         ret = func(*args,**kwargs)   # func是被装饰的函数 在这里被调用
    #         ‘‘‘在函数被调用之后添加的代码‘‘‘
    #         return ret
    #   @wrapper1
    #   @wrapper2
    #   def func():
    #       print(‘111‘)
# 迭代器和生成器 —— 两天
# 内置函数 —— 两天
View Code

2.可迭代及可迭代协议

假如我现在有一个列表l=[‘a‘,‘b‘,‘c‘,‘d‘,‘e‘],我想取列表中的内容,有几种方式?

首先,我可以通过索引取值l[0],其次我们是不是还可以用for循环来取值呀?

你有没有仔细思考过,用索引取值和for循环取值是有着微妙区别的。

如果用索引取值,你可以取到任意位置的值,前提是你要知道这个值在什么位置。

如果用for循环来取值,我们把每一个值都取到,不需要关心每一个值的位置,因为只能顺序的取值,并不能跳过任何一个直接去取其他位置的值。

但你有没有想过,我们为什么可以使用for循环来取值?

for循环内部是怎么工作的呢?

要了解for循环是怎么回事儿,咱们还是要从代码的角度出发。

首先,我们对一个列表进行for循环。

for i in [1,2,3,4]:  
    print(i)

上面这段代码肯定是没有问题的,但是我们换一种情况,来循环一个数字1234试试

 
for i in 1234
    print(i) 

结果:
Traceback (most recent call last):
  File "test.py", line 4, in <module>
    for i in 1234:
TypeError: ‘int‘ object is not iterable
 

看,报错了!报了什么错呢?“TypeError: ‘int‘ object is not iterable”,说int类型不是一个iterable,那这个iterable是个啥?

技术分享图片

假如你不知道什么是iterable,我们可以翻翻词典,首先得到一个中文的解释,尽管翻译过来了你可能也不知道,但是没关系,我会带着你一步一步来分析。

迭代和可迭代协议
 
什么叫迭代
现在,我们已经获得了一个新线索,有一个叫做“可迭代的”概念

首先,我们从报错来分析,好像之所以1234不可以for循环,是因为它不可迭代。那么如果“可迭代”,就应该可以被for循环了。

这个我们知道呀,字符串、列表、元组、字典、集合都可以被for循环,说明他们都是可迭代的

我们怎么来证明这一点呢?

 
from collections import Iterable
                             
l = [1,2,3,4]                
t = (1,2,3,4)                
d = {1:2,3:4}                
s = {1,2,3,4}                
                             
print(isinstance(l,Iterable))
print(isinstance(t,Iterable))
print(isinstance(d,Iterable))
print(isinstance(s,Iterable))
 

结合我们使用for循环取值的现象,再从字面上理解一下,其实迭代就是我们刚刚说的,可以将某个数据集内的数据“一个挨着一个的取出来”,就叫做迭代

可迭代协议

可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了__iter__方法。

3.迭代器

技术分享图片
 迭代器的概念
# 迭代器协议 —— 内部含有__next__和__iter__方法的就是迭代器

# 迭代器协议和可迭代协议
# 可以被for循环的都是可迭代的
# 可迭代的内部都有__iter__方法
# 只要是迭代器 一定可迭代
# 可迭代的.__iter__()方法就可以得到一个迭代器
# 迭代器中的__next__()方法可以一个一个的获取值

# for循环其实就是在使用迭代器
# iterator
# 可迭代对象
# 直接给你内存地址
# print([].__iter__())
# print(range(10))

#for
#只有 是可迭代对象的时候 才能用for
#当我们遇到一个新的变量,不确定能不能for循环的时候,就判断它是否可迭代

# for i in l:
#     pass
#iterator = l.__iter__()
#iterator.__next__()

#迭代器的好处:
    # 从容器类型中一个一个的取值,会把所有的值都取到。
    # 节省内存空间
        #迭代器并不会在内存中再占用一大块内存,
            # 而是随着循环 每次生成一个
            # 每次next每次给我一个
# range
# f
# l = [1,2,3,45]
# iterator = l.__iter__()
# while True:
#     print(iterator.__next__())

# print(range(100000000000000))
# print(range(3))
# print(list(range(3)))
# def func():
#     for i in  range(2000000):
#         i = ‘wahaha%s‘%i
#     return i

# 生成器 —— 迭代器
# 生成器函数 —— 本质上就是我们自己写得函数
# 生成器表达式
l = [1,2,3,4,5]
for i in l:
    print(i)
    if i == 2:
        break

for i in l:
    print(i)
View Code

4.生成器

我们知道的迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。

如果在某些情况下,我们也需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器。

 

Python中提供的生成器:

1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行

2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表

 

生成器Generator:

  本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)

  特点:惰性运算,开发者自定义

技术分享图片代码

 

以上是关于python学习第十三天 迭代器 生成器的主要内容,如果未能解决你的问题,请参考以下文章

python学习第十三天:带参数装饰器和迭代器

2018.09.28python学习第十三天part2

第十三天 叠加多个装饰器 迭代器 生成器

基础学习之第十三天(迭代器与生成器)

python学习第十三章

第十三天-生成器