• 33-高级特性之generator(1)


    1. 列表生成式

    ################列表生成式
    #method_1 {太原始,不推荐}
    L = []
    for i in range(1,11): #[1,11)
        L.append(i*i)
    print(L)
    
    
    #method_2
    #######最佳的办法
    L1 = [x*x for x in range(1,11)]
    print(L1)
    
    L2 = [x*x for x in range(1,11) if (x%2 == 0)]
    print(L2)
    
    L3 = [m+n for m in "ABC" for n in "XYZ"]
    print(L3)
    
    import os
    dir = [d for d in os.listdir('.')] #.表示当前目录下
    print(dir)
    
    #考虑到for 可以同时迭代两个甚至更多变量,把他应用到 列表生成式
    dict = {'name':'haozhang', 'gender':'male', 'city':'HG'}
    for k,v in dict.items():
        print(k,':',v)
    print("
    ")
    
    L4 = [k+':'+v for k,v in dict.items()]
    print(L4)
    
    #
    L = ['ABC', 'Hong', 'KONG']
    print(L)
    L5 = [s.lower() for s in L]
    print(L5)
    
    L6 = ['ABC', 'HongKong', 123, '456']
    print(L6)
    L7 = [s.lower() for s in L6 if isinstance(s, str)]
    print(L7)
    L8 = [s.lower() for s in L6] #没有过滤整数,会报错
    

    2. generator初步:

    • 理解yield关键字的作用:

    • 首先yield就像一个中断源,代码执行到yield处就中断,cpu执行其他函数去了。例如,count = yield yyy,代码到这一行,刚刚碰到yield就暂停本generator函数,并保存当前状态等待恢复。
    • 直到next(对象名),或者send(实参),来激活这一行语句。
    • 暂停yield的同时,向主调函数返回yyy {就这个功能而言,yield yyy等价于return yyy}
    • 终上所述,yield首先是挂起当前的generator函数,然后可以返回一个数据给主调函数(即使用了next(),send(),或者用for迭代这个generator函数的语句)。
    • 用for迭代这个generator函数 本质还是利用了next(对象名)
    • 代码测试:

      测试generator

      以创建list作为对比

      L = [x*x for x in range(1,11)]
      print(L)

      G = (x*x for x in range(1,11)) #Generator表达式
      print(G)
      print(next(G))
      print(next(G))
      print(" ")

      g = (xx for x in range(1,11)) #构造了一个generator类并返回了一个它的对象
      for y in g: #迭代g的每一项x
      x
      print(y)
      print(" ")

      测试第二种generator :Generator函数

      采用函数方式

      def fib(n):
      i,a,b = 0,0,1 #fib(0) = 0, fib(1) = 1, fib(2) = 1
      while i < n: #执行n-1次,i的范围是[0,n-1],因为默认是fib(1),所以后面都是返回fib(n)
      print(b)
      a,b = b,a+b
      i = i + 1
      return 'done'
      fib(6)
      print(" ")

      采用yield关键字,用generator实现

      def G_fib(n): #实际上等价于创建了一个generator类,虽然表面上是一个函数
      i,a,b = 0,0,1
      while i < n: #[0,n-1]
      yield b #此次返回并暂时挂起
      a,b = b,a+b
      i = i + 1
      g2 = G_fib(6) #返回一个generator类创建的对象g2
      print(g2)
      for x in g2: #迭代g2中的每一项即:fib(i)
      print(x)
      print(" ")

      创建一个产生所有奇数的generator

      def odd():
      i = 1
      while True:
      yield i
      i = i + 2
      g3 = odd()
      print(next(g3))
      print(next(g3))
      print(next(g3))
      print(" ")

      理论上可以通过for x in g3 遍历足够多的,或者说是所有的奇数,但这里没有必要

      {即节省内存,因为每次只会创建一个item;另外,非常的简洁地可以代表一个无穷的stream}

      实现一个2^n{乘方}

      def powtwo(n):
      i = 1
      while i <= n: #[1,n],操作了n次
      yield 2 ** i
      i += 1

      for x in powtwo(5): #计算2^5
      print("中间过程依次是:",x)
      print("the result is = ",x)
      print(" ")

      '''
      实现一个假设我们有一个快餐连锁店的日志。

      日志的第四列是每小时售出的披萨数量,我们想对近5年的这一数据进行求和。

      假设所有数据都是字符,不可用的数据都以"N/A"表示

      with open('sells.log') as file:
      pizza_col = (line[3] for line in file) #取第4列,构建一个tuple
      per_hour = (int(x) for x in pizza_col if x != 'N/A') #依据上面的tuple构建generator表达式
      print("Total pizzas sold = ",sum(per_hour))
      '''

      #########################################################################################

      '''
      最后一个主题:获取generator中,用return关键字返回的值
      {因为现在只会返回yield关键字所带的值}

      通过解析StopIteration的内容获取return关键字后的值

      以获取杨辉三角的最后return的'haozhang'为例

      '''

      做法1

      def triangles():
      N = [1] #要求返回N为list
      while True:
      yield N
      N.append(0) #辅助元:处理每一行两边{左边一个1,右边一个1},保证它们在下一行依旧为1:0+1还是1
      #append完之后,本行{假设为k-1} 新增N[k] = 0,同时在python中N[k]作为倒数第一个元素,也为N[-1]
      #具体实现方法:对于下一行{假设是k}的N, N[0] = N[-1]+N[0],N[k] = N[k-1]+N[k]
      N = [N[i-1]+N[i] for i in range(len(N))]

      i = 0
      for L in triangles(): #匿名创建了triangles的generator对象,并迭代
      print(L)
      i += 1
      if (i == 10): #打印10行
      break
      print(" ")

      做法2:错位相加{L1左边和L2右边各自添加一个[0],即长度加1}

      [0]+N等价于在N左边加了一个元素0,N+[0]等价于在N右边加了一个元素0{可在控制台测试}

      zip(x, y)等价于:若x=[x1,x2], y=[y1,y2], 则zip(x,y) = [(x1,y1), (x2,y2)]

      def triangles_2():
      N = [1]
      while True:
      yield N
      N = [sum(i) for i in zip([0]+N, N+[0])]
      j = 0
      for L2 in triangles_2():
      print(L2)
      j += 1
      if (j == 10): #输出10行即停止
      break
      print(" ")

      加入try-catch实现把return关键字返回的值打印出来

      def My_Triangle(n):
      N = [1]
      i = 0
      while (i < n): #[0,n-1]次
      yield N
      N = [sum(i) for i in zip([0]+N, N+[0])]
      i += 1
      return "haozhang is ok" #我想把这个也拿出来!

      GT = My_Triangle(10)
      while True:
      try:
      x = next(GT)
      print(x)
      except StopIteration as e:
      print("Generation return value is: ", e.value)
      break

    • 理解send()的作用:

    • next()等价于send(None),系统向generator发信号“在中断处重新启动”就是send(实参)的功劳,send()才是核心。
    • send(数据值)等价于 给yield左边的变量赋值,例如:count = yield x,当使用 send(555)激活上述的yield时,等价于执行 count = 555,然后再执行count=yield的下一句代码
    • 终上所述,send(实参)可以给generator函数传入数据,并同时激活这个generator函数
    • 代码测试:

      def stupid_fib(n):
      index = 0
      a = 0
      b = 1
      while index < n:
      sleep_cnt = yield b
      print('let me think {0} secs'.format(sleep_cnt))
      time.sleep(sleep_cnt)
      a, b = b, a + b
      index += 1

      print('-'10 + 'test yield send' + '-'10)
      N = 20
      sfib = stupid_fib(N) #得到一个generator对象
      fib_res = next(sfib) #启动generator
      while True:
      print(fib_res)
      try:
      fib_res = sfib.send(random.uniform(0, 0.5)) #给函数传入暂停时长sleep_cnt,并重新激活generator
      except StopIteration:
      break

    参考文献:

    1. http://python.jobbole.com/86069/
    2. 尚学堂python视频
    3. 廖雪峰python3
  • 相关阅读:
    1030 完美数列 (25 分)
    1029 旧键盘 (20 分)
    数据库命令失败原因汇总
    代码有中文括号,导致错误
    win10笔记本触控板使用指南
    (已解决)vsC#控制台应用添加System.Windows.Forms引用失败(精通C#)
    ildasm中Ctrl+M闪退的问题(已解决, 精通C# 15.1)
    C#控制台应用(.NET Core)添加System.Windows.Forms失败(已解决)
    知识点_指针_增加对指针的理解
    自己写出的Bug_应是%f却写成%d
  • 原文地址:https://www.cnblogs.com/LS1314/p/8504552.html
Copyright © 2020-2023  润新知