zoukankan      html  css  js  c++  java
  • python — 生成器、推导式、递归

    1 生成器(函数的变异)

    判断一个函数是否是生成器函数:只需看函数内部是否有yield

    # 生成器函数(内部是否包含yield)
    def func():
        print('F1')
        yield 1
        print('F2')
        yield 2
        print('F3')
        yield 100
        print('F4')
    # (只要有yield)函数内部代码不会执行,返回一个 生成器对象 。
    v1 = func()
    # 生成器是可以被for循环,一旦开始循环那么函数内部代码就会开始执行。
    for item in v1:
        print(item)
    

    循环流程:

      1. for循环开始第一次循环,先执行yield前面的代码,执行到yield时,返回yield的值给item并停止第一次循环。
      2. 第二次循环:从上次循环的yield后面开始执行代码,执行到第二个yield(yield2)时,返回yield2的值给item并停止第二次循环。
      3. 直到循环完所有的yield,循环自动终止
      def func():
          count = 1
          while True:
              yield count
              count += 1
              
      val = func()
      
      for item in val:
          print(item)
      

      总结:函数中如果存在yield,那么该函数就是一个生成器函数,调用生成器函数会返回一个生成器,生成器只有被for循环时,生成器函数内部的代码才会执行,每次循环都会获取yield返回的值。

      def func():
          count = 1
          while True:
              yield count
              count += 1
              if count == 100:
                  return
      
      val = func()
      for item in val:
          print(item)
      

      示例:读文件

      def func():
          """
          分批去读取文件中的内容,将文件的内容返回给调用者。
          :return:
          """
          cursor = 0
          while True:
              f = open('db', 'r', encoding='utf-8')# 通过网络连接上redis
              # 代指   redis[0:10]
              f.seek(cursor)
              data_list =[]
              for i in range(10):
                  line = f.readline()
                  if not line:
                      return
                  data_list.append(line)
              cursor = f.tell()
              f.close()  # 关闭与redis的连接
      
      
              for row in data_list:
                  yield row
      
      
      for item in func():
          print(item)
      

      redis源码示例

      生成器作用:

      • 生成数据

      • 是一种特殊的迭代器

        def func():
            yield 1
            yield 2
            yield 3
        
        v = func()
        result = v.__next__()
        print(result)
        result = v.__next__()
        print(result)
        result = v.__next__()
        print(result)
        result = v.__next__()
        print(result)
        
      • 也是特殊的可迭代对象

        def func():
            yield 1
        
        v = func()
        result = v.__iter__()
        print(result)
        

      其他知识:

      • yeild from关键字 (从xxx中一点点获取)

        def base():
            yield 88
            yield 99
        
        def func():
            yield 1
            yield 2
            yield from base()   # 从base()中一点点获取
            yield 3
        
        result = func()
        
        for item in result:
            print(item)
        

      生成器的send方法

      def func():
          print(123)
          n = yield 'aaa'
          print('-->',n)
          yield 'bbb'
      
      g = func()
      print(g)
      n = next(g)
      print(n)
      print('-'*20)
      next(g)   # g.send('uysdfhfoiusyg')与next(g)的作用一样
      

      注意:

      • 1.生成器取一次就没有了,再次取时内部为空

      • 2.惰性运算 :不取不执行

        ret = filter(lambda n:n%3==0,range(10))
        # ret是迭代器
        print(len(list(ret)))   # 4  # list(ret) = [0,3,6,9]
        print(len(list(ret)))   # 0  # list(ret) = []
        

    2 推导式

    2.1 列表推导式

    • 1.目的

      方便的生成一个列表

    • 2.基本格式

      • 变量 = [for循环的变量 for循环一个可迭代对象]

      • v1 = [i for i in 可迭代对象 ]
        v2 = [i for i in 可迭代对象 if 条件 ] # 条件为true时才进行append

      • 练习

        v1 = [ i for i in 'alex' ]   # ['a','l','e','x']
        v2 = [i+100 for i in range(10)]   # [100,101,102,103,104,105,106,107,108,109]
        v3 = [99 if i>5 else 66  for i in range(10)]   # [66,66,66,66,66,66,99,99,99,99]
        
        def func():
            return 100
        v4 = [func for i in range(10)]   # [func,func,func,func,func,func,func,func,func,func,]
        
        v5 = [lambda : 100 for i in range(10)]   # [lambda : 100,lambda : 100,lambda : 100,lambda : 100,lambda : 100,lambda : 100,lambda : 100,lambda : 100,lambda : 100,lambda : 100]
        result = v5[9]()    # 100
        
        v6 = [lambda :i for i in range(10)]   # [lambda :i,lambda :i,lambda :i,lambda :i,lambda :i,lambda :i,lambda :i,lambda :i,lambda :i,lambda :i,]
        result = v6[5]()   # 9
        
        v7 = [lambda x:x*i for i in range(10)]
        # 1.请问 v7 是什么?
         v7 = [lambda x:x*i,lambda x:x*i,lambda x:x*i,lambda x:x*i,lambda x:x*i,lambda x:x*i,lambda x:x*i,lambda x:x*i,lambda x:x*i,lambda x:x*i,]
        # 2.请问 v7[0](2) 的结果是什么?    v7[0](2) = 18
        
        def num():
            return [lambda x:i*x for i in range(4)]
        # num() -> [函数,函数,函数,函数]
        print([ m(2) for m in num() ]) # [6,6,6,6]
        
        # ##################### 筛选 #########################
        v8 = [i for i in range(10) if i > 5]   # [6,7,8,9]
        

    2.2 集合推导式

    • 1.目的

      方便的生成一个集合

    • 2.基本格式

      • 变量 = {for循环的变量 for循环一个可迭代对象}

      • v1 = { i for i in 可迭代对象 }
        v2 = { i for i in 可迭代对象 if 条件 } # 条件为true时才进行append

        v1 = { i for i in 'alex' }   # {'a','l','e','x'}
        

    2.3 字典推导式

    • 1.目的

      方便的生成一个字典

    • 2.基本格式

      v1 = { 'k'+str(i):i for i in range(10) }
      #{'K0':0,'K1':1,'K2':2,'K3':3,'K4':4,'K5':5,'K6':6,'K7':7,'K8':8,'k9':9}
      
      v1 = { 'k':i for i in range(10) }   # {'k':9} #字典的键存在,则新值覆盖旧值,不存在则更新。
      

    2.4 生成器推导式

    # def func():
    #     result = []
    #     for i in range(10):
    #         result.append(i)
    #     return result
    # v1 = func()
    v1 = [i for i in range(10)] # 列表推导式,立即循环创建所有元素。
    print(v1)
    
    # def func():
    #     for i in range(10):
    #         yield i
    # v2 = func()
    v2 = (i for i in range(10)) # 生成器推导式,创建了一个生成器,内部循环为执行。
    
    # 示例一
    def func():
        result = []
        for i in range(10):
            result.append(i)
        return result
    v1 = func()
    for item in v1:
       print(item)
    
    # 示例二
    def func():
        for i in range(10):
            def f():
                return i
            yield f
    v1 = func()
    for item in v1:
        print(item())
    
    # 示例三:
    v1 = [i for i in range(10)] # 列表推导式,立即循环创建所有元素。
    v2 = (lambda :i for i in range(10))
    for item in v2:
        print(item())
    

    3 递归

    递归就是 函数自己调用自己(缺点:效率低)

    python默认支持的递归最大数是1000次

    def func():
        print(1)
        func()
        
    func()
    
    def func(i):
        print(i)
        func(i+1)
        
    func(1)
    
    def func(a,b):          # 只能递归1000次的斐波那契
        # 1
        # 1
        # 2
        # 3 
        # 5 
        print(b) 
        func(b,a+b)
        
    func(0,1)
    
    def func(a):
        if a == 5:
            return 100000
        result = func(a+1) + 10
        return result 
    
    v = func(1)
    

    1555402471461

    # 递归的返回值
    def func(a):
        if a == 5:
            return 100000
        result = func(a+1) + 10
    
    v = func(1)
    name = 'alex'
    def func():
        def inner():
            print(name)
         return inner
    v =func()
    
  • 相关阅读:
    python使用代理访问服务器
    python请求服务器时如何隐藏User-Agent
    python利用有道翻译实现“语言翻译器”的功能
    python请求服务器图片并下载到本地磁盘
    python的搜索路径与包(package)
    Python生成器(yield)
    Python迭代器(斐波拉切数列实例)
    Python定制容器
    Python描述符:property()函数的小秘密
    Python类属性访问的魔法方法
  • 原文地址:https://www.cnblogs.com/yangjie0906/p/11215849.html
Copyright © 2011-2022 走看看