zoukankan      html  css  js  c++  java
  • Python生成器

     1 def f(n):
     2     return n**3
     3 
     4 #列表生成式
     5 a = [f(x) for x in range(10)]
     6 
     7 print (a)
     8 print(type(a))
     9 
    10 
    11 
    12 
    13 
    14 
    15 t = ('123', 8)#元组
    16 a, b = t # a=t[0], b=t[1] ,数量必须一致
    17 print(a)
    18 print(b)

    执行结果:

    [0, 1, 8, 27, 64, 125, 216, 343, 512, 729]
    <class 'list'>
    123
    8
    
    Process finished with exit code 0

    生成器

    任何使用yield的函数都称之为生成器

    使用yield,可以让函数生成一个序列,该函数返回的对象类型是"generator",通过该对象连续调用__next__()方法返回序列值。

    生成器函数只有在调用__next()__方法的时候才开始执行函数里面的语句,比如:

    def count(n):
      print ( "cunting" )
      while n > 0:
        yield n  #生成值:n
        n -= 1
        print("hi")
    
    c = count(5)
    
    h = c.__next__()   # 到yield后不执行
    print(h)
    l = c.__next__()   # 从上一次yield后开始执行
    print(l)
    print(10*"==")
    
    generator = count(6)
    for i in generator:
        print(i)
    print(generator)  # 任何使用yield的函数都称之为生成器

    执行结果:

    cunting
    5
    hi
    4
    ====================
    cunting
    6
    hi
    5
    hi
    4
    hi
    3
    hi
    2
    hi
    1
    hi
    <generator object count at 0x7f42cb3980a0>
    
    Process finished with exit code 0

    在调用count函数时:c=count(5),并不会打印"counting"只有等到调用c.__next__()时才真正执行里面的语句。每次调用__next__()方法时,count函数会运行到语句yield n处为止,__next__()的返回值就是生成值n,再次调用__next__()方法时,函数继续执行yield之后的语句

    通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

    所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。

    要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

    1 s = (x*2 for x in range(5)) #生成器
    2 
    3 print(s) # <generator object <genexpr> at 0x7f510c34a360>
    4 
    5 print(next(s)) # 等价于 s.__next__()    0
    6 
    7 print(next(s)) # 只能按顺序取值
    8 
    9 print(next(s))

    执行结果

    <generator object <genexpr> at 0x7fc5b2af5360>
    0
    2
    4
    
    Process finished with exit code 0

    生成器一共两种创建方式:

    1.s = (x*2 for x in range(5))      而列表生成器为[x*2 for x in range(5)]

    2. yield

     1 def foo():
     2     print('ok1') # foo()时不会被执行
     3     yield 1
     4 
     5     print("ok2")
     6     yield 2
     7 
     8 
     9 g=foo() #生成生成器对象
    10 print(g) # foo()成为了生成器对象 <generator object foo at 0x7fc04a8d4360>
    11 
    12 a = next(g) #进入生成器,yield相当于return,执行到yield不会再向下执行
    13 
    14 b = next(g) #到yield 1,再print ('ok2')
    15 print(a)
    16 print(b)
    17 
    18 
    19 print("
    ")
    20 
    21 for i in foo(): # i 是返回值 1, 2  
    22     print(i)

    执行结果:

    <generator object foo at 0x7f8fb17d5360>
    ok1
    ok2
    1
    2
    
    
    ok1
    1
    ok2
    2
    
    Process finished with exit code 0

    什么是可迭代对象(对象拥有iter方法的)

    l = [1, 2, 3]
    
    l.__iter__()
    

     send

     1 def bar():
     2     print('ok')
     3     count = yield 1 #yield先返回
     4     print(count)
     5 
     6     yield 2
     7 
     8 b = bar()
     9 
    10 s = b.send(None) #相当于next(b) 第一次send前如果没有next,只能传一个send(None),并不知道将值传给谁,只能用None
    11 print(s) #yield返回值
    12 
    13 ret = b.send('eeee') #传给count
    14 print(ret)

    可以断点执行(debug),了解具体的执行过程,第10行返回1(yield 1,s为1),第13行(count = 'eeee'),并且print(count),yield 2返回2,ret为2。

    执行结果:

    ok
    1
    eeee
    2
    
    Process finished with exit code 0
  • 相关阅读:
    swift3.0更新内容
    Core Animation
    UIBezierPath精讲
    iOS-Core-Animation-Advanced-Techniques(原文来自cocoachina)
    iOS上图形和动画处理
    使用GCD(转自唐巧的技术博客)
    UITableView的cell的分割线位置
    swift深入理解闭包
    Swift控制器加载xib Swift Controller'view load from xib
    -[UIWindow viewForFirstBaselineLayout]: unrecognized selector sent to instance
  • 原文地址:https://www.cnblogs.com/112358nizhipeng/p/9497151.html
Copyright © 2011-2022 走看看