zoukankan      html  css  js  c++  java
  • 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__方法,不需要我们去实现)

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

    代码
  • 相关阅读:
    手脱ASPack2.12壳(练习)
    手脱UPX3.91壳(练习)
    如何在程序执行前插入可执行代码(算是吾爱的作业吧,活学活用)
    小米笔记本粉丝感恩狂欢趴【慎入!!】
    picpick截屏软件脱壳
    JAVA反序列化漏洞
    Java中的数据类型
    Java中常见的包
    Scrapy
    PHPstorm 函数时间注释的修改
  • 原文地址:https://www.cnblogs.com/xubohua/p/8185334.html
Copyright © 2011-2022 走看看