zoukankan      html  css  js  c++  java
  • 《Python》 生成器和列表推导式

    一、初识生成器:

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

        1、Python中提供的生成器:

          1、生成器函数:

            使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。

          2、生成器表达式:

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

        2、生成器Generator:

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

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

    二、生成器函数:

        一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return。

        yield和return的区别:

          return:结束函数,给函数的执行者返回值。

          yield:不会结束函数,一个next对应一个yield,给 生成器对象.__next__() 返回值

        生成器函数vs迭代器:

          1.自定制取值:

     1 只能一个一个取值:
     2 l1 = [1,2,3,4,5]
     3 l1.__iter__()
     4 
     5 可以自定义取值:
     6 def func1(x):
     7     x += 1
     8     yield x
     9     x += 3
    10     yield x
    11     x += 5
    12     yield x
    13 g1 = func1(5)
    14 print(g1.__next__())
    15 print(g1.__next__())
    16 print(g1.__next__())
    自定制的区别

          2、内存级别的区别:

            迭代器是需要可迭代对象进行转换,可迭代对象非常占内存。

            生成器直接创建,不需要转化,从本质就节省内存。

    def func1():
        for i in range(1000000):
            yield i
    g1 = func1()
    for i in range(50):
        print(g1.__next__())
    生成器按需取值
     1 import time
     2 def genrator_fun1():
     3     a = 1
     4     print('现在定义了a变量')
     5     yield a
     6     b = 2
     7     print('现在又定义了b变量')
     8     yield b
     9 
    10 g1 = genrator_fun1()
    11 print('g1 : ',g1)       #打印g1可以发现g1就是一个生成器
    12 print('-'*20)   #我是华丽的分割线
    13 print(next(g1))
    14 time.sleep(1)   #sleep一秒看清执行过程
    15 print(next(g1))
    16 
    17 初识生成器函数
    初始生成器函数

    生成器有什么好处呢?就是不会一下子在内存中生成太多数据

    假如我想让工厂给学生做校服,生产2000000件衣服,我和工厂一说,工厂应该是先答应下来,然后再去生产,我可以一件一件的要,也可以根据学生一批一批的找工厂拿。
    而不能是一说要生产2000000件衣服,工厂就先去做生产2000000件衣服,等回来做好了,学生都毕业了。。。

    def produce():
        """生产衣服"""
        for i in range(2000000):
            yield "生产了第%s件衣服"%i
    
    product_g = produce()
    print(product_g.__next__()) #要一件衣服
    print(product_g.__next__()) #再要一件衣服
    print(product_g.__next__()) #再要一件衣服
    num = 0
    for i in product_g:         #要一批衣服,比如5件
        print(i)
        num +=1
        if num == 5:
            break
    生成器按需取值

    三、send

       send和next一样,也是对生成器取值(执行一个yield)的方法。

       send可以给上一个yield传值。

       第一次取值永远都是next。

       最后一个yield永远也得不到send传的值。

    def generator():
        print(123)
        content = yield 1
        print('=======',content)
        print(456)
        yield2
    
    g = generator()
    ret = g.__next__()
    print('***',ret)
    ret = g.send('hello')   #send的效果和next一样
    print('***',ret)
    send的用法

    四、列表推导式和生成器表达式   

        1.把列表解析的[]换成()得到的就是生成器表达式

        2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存

        3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。

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

            优点:一行解决,方便。

            缺点:容易着迷,不易排错,不能超过三次循环。

               列表推导式不能解决所有列表的问题,所以不要太刻意用。

          1、循环模式:[ 变量(加工后的变量) for  变量  in  可迭代对象 ]

            prite([ i for i in range(1,101)]) # 循环打印1~100

            prite([ ‘Python第%s期’ % i for i in range(1,16)]) 

          2、筛选模式:[ 变量(加工后的变量)for  变量  in  可迭代对象  if  条件 ]

            prite([ i  for  i  in  range(1,31)  if  i  %  3  ==  0 ])  #打印30以内能被3整除的数

            prite([ i ** 2  for  i  in  range(1,31)  if  i  %  3  ==  0 ])  #打印30以内能被3整除的数的平方

    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    
    print([name for lst in names for name in lst if name.count('e') >= 2])  # 注意遍历顺序,这是实现的关键
    找到嵌套列表中名字含有两个‘e’的所有名字     

        二、字典推导式:      

    mcase = {'a': 10, 'b': 34}
    mcase_frequency = {mcase[k]: k for k in mcase}
    print(mcase_frequency)
    将一个字典的key和value对调
    mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
    mcase_frequency = {k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase.keys()}
    print(mcase_frequency)
    合并大小写对应的value值,将k统一成小写

        三、集合推导式:

    squared = {x**2 for x in [1, -1, 2]}
    print(squared)
    # Output: set([1, 4])
    计算列表中每个值的平方,自带去重功能
  • 相关阅读:
    Java中用JXL导出Excel代码详解
    oracle之FUNCTION拙见
    oracle 存储过程详细介绍(创建,删除存储过程,参数传递等)1
    Crontab使用方式
    Git使用技巧(3)-- 远程操作
    Git使用技巧(2)-- 基本操作
    Git使用技巧(1)-- 配置【持续更新】
    Vim使用技巧(1) -- 普通模式技巧 【持续更新】
    sublime使用技巧(4)-- 其他技巧【持续更新】
    sublime使用技巧(3)-- 常用快捷键【持续更新】
  • 原文地址:https://www.cnblogs.com/yzh2857/p/9506080.html
Copyright © 2011-2022 走看看