zoukankan      html  css  js  c++  java
  • python之迭代器,生成器以及列表推导式

     

    可迭代对象

      对象内部含有 __iter__方法就是可迭代对象。

        可迭代对象:str list dict tuple set range()

      可迭代对象满足可迭代协议

    判断一个对象是否可迭代:

      第一个方法:

    print('__iter__ in dir(s))
    

      第二个方法:

    from collections import Iterable  # 判断可迭代对象
    from  collections import Iterator   # 判断迭代器
    
    print(isinstance('alex', Iterable))  # 判断类型
    

     

    迭代器:

      对象内部含有__iter__方法,且含有__next__方法就是迭代器。

    判断一个对象是否迭代器:

     print('__next__' in dir(f))
    

      

    # 可迭代对象
    # for i in 'abc':
    # #     print(i)
    
    # 对象内部含有 __iter__ 方法就是可迭代对象。
    # s = '123'
    # print(dir(s))
    
    # 判断一个对象是否可迭代对象:
    # 第一种方法
    # print('__iter__' in dir(s))
    
    # 第二种方法
    from collections import Iterable  # 判断可迭代对象
    from  collections import Iterator   # 判断迭代器
    
    print(isinstance('alex', Iterable))  # 判断类型
    
    
    
    # 迭代器
    # 判断一个对象是否可迭代器
    f = open('a', encoding='utf-8', mode='w')
    print('__next__' in dir(f))
    

      

    可迭代对象 vs 迭代器

    • 1. 可迭代对象不能取值,迭代器是可以取值的。
    • 可迭代对象 --->(转化成) 迭代器:
    • 2. 迭代器非常节省内存。
    • 只加载一个内存地址,next一下,加载这个内存的地址+
    • 3. 迭代器每次只会取一个值。
    • 4. 迭代器单向的,不反复,一条路走到头。会记录地址


    数据量很大 只是取值 用迭代器。




    while循环 模拟 for 循环内部机制:

    • 1. 将可迭代对象转化成迭代器。
    • 2. 调用__next__ 方法取值
    • 3. 利用异常处理停止报错
    # 可迭代对象 --->(转化成) 迭代器:
    lis = [1, 2, 3] # 可迭代对象
    ite1 = lis.__iter__()  # 迭代器
    print(ite1)
    
    # 迭代器如何取值  next一次,取一个值
    print(ite1.__next__())  # 写一步 取一个
    
    
    # while循环 模拟 for 循环:
    # 1. 将可迭代对象转化成迭代器。
    # 2. 调用__next__ 方法取值
    # 3. 利用异常处理停止报错
    
    
    s = 'sdgs'
    iter2 = s.__iter__()
    while 1:
        try:
            print(iter2.__next__())
        except StopIteration:
            break
    

      

    生成器

    生成器:就是自己python用代码写的迭代器,生成器的本质就是迭代器。

    用一下两种方式构建一个生成器:

    • 通过生成器函数
    • 生成器表达式
    def func2(x):
        x += 1
        print(111)
        yield x
        print(222)
    g_obj = func2(5)   # 生成器函数对象
    # print(g_obj)  <generator object func2 at 0x000001933AEB9408>
    # g_obj.__next__()  #111
    # g_obj.__next__()  #222
    # 一个next对应一个yield
    # yield 将值返回给 生成器对象.__next__()
    

    yield return 区别

    • return结束函数,给函数的执行者返回值
    • yield 不会结束函数,一个next对应一个yield,给 生成器对象.__next__() 返回值

    生成器函数 迭代器

    • 区别区别1:自定制区别
    • 区别2:内存级别的区别 迭代器需要可迭代对象进行转化。

           可迭代对象是非常占内存的 生成器是直接创建,不需要转化。从本质上就节省内存。

      

    区别1 自定制去呗
    
    # l1 = [1, 2, 3, 4, 5]
    # l1.__iter__()
    
    
    # def func1(x):
    #     x += 1
    #     yield x
    #     x += 3
    #     yield x
    #     x += 5
    #     yield x
    #
    #
    # g1 = func1(5)
    # print(g1.__next__())
    # print(g1.__next__())
    # print(g1.__next__())
    
    
    
    # 区别2 内存级别区别
    # def func3():
    #     for i in range(100000):
    #         yield i
    # g2 = func3()
    # for i in range(50):
    #     print(g2.__next__())
    
    def func(x):
        x += 1
        yield x
        x += 2
        yield x
    
    # 得到两个生成器对象
    # print(func(8).__next__())  # 9
    # print(func(8).__next__())   # 9
    
    
    # 得到一个生成器对象
    g = func(8)
    print(g.__next__())  # 9
    print(g.__next__())  # 11
    生成器的赋值

    send 与 next 区别  

    • send 与 next 一样,也是对生成器取值(执行一个yield)的方法
    • send 可以给 上一个yield传值。
    • 第一次取值永远都是next
    • 最后一个yield永远也得不到send传的值
    # send 与 next
    def func1():
        # print(1)
        count = yield 6
        print(count)
        # print(2)
        yield 7
        # print(3)
        yield 8
    
    
    g1 = func1()
    # next(g1)
    print(next(g1))
    g1.send('alex')
    next(g1)
    

      

    列表推导式:一行代码几乎搞定你需要的任何列表

    • 循环模式 [变量(加工后的变量) for 变量 in iterable]

    • 筛选模式 [变量(加工后的变量) for 变量 in iterable if 条件]

    l = [i for i in range(1,101)]
    print(l)
    
    
    l = ['python %s 期' % i for i in range(1, 16)]
    print(l)
    
    l = [i**2 for i in range(1, 11)]
    print(l)
    循环模式
    l = [i for i in range(1, 31) if i % 2 == 0]
    print(l)
    
    l = [i for i in range(1, 31) if i % 3 == 0]
    print(l)
    
    l = [i**2 for i in range(1, 31) if i % 3 == 0]
    print(l)
    
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    l = [j for i in names for j in i if j.count('e') == 2]
    print(l)
    筛选模式

    列表推导式:
    优点:一行解决,方便。
    缺点:容易着迷,不易排错,不能超过三次循环
    列表推导式不能解决所有列表的问题,所以平时的代码不要太刻意用。

    # 生成器表达式: 将列表推导式的 [] 换成 () 即可
    g = (i for i in range(100))
    print(g.__next__())
    print(next(g))
    
    #
    

      

  • 相关阅读:
    prototype
    JS中我们为什么要new个实例而不直接执行
    购物车,实现增删改查;无bug,还有一个直接修改购物车数量功能未实现
    jquery中判断复选框有没有被选上
    git
    scss
    gulp基本操作
    nodejs,,一些基本操作--server。js
    node.js介绍及简单例子
    自己定义jquery插件轮播图
  • 原文地址:https://www.cnblogs.com/eaoo/p/9494142.html
Copyright © 2011-2022 走看看