迭代器、生成器

 

迭代器:

 

  可迭代对象:要遵守迭代协议,只要有__iter__方法的,就是可迭代对象,可以被for循环

 

  迭代器:要遵守迭代器的协议,有__iter__和__next__方法的就叫迭代器

 

      创建一个迭代器 == 可迭代对象.__iter__()

 

    使用迭代器,就是 == 迭代器.__next__()

 

lst = [1,2,3]                (三个获取的都是1)
l1 = lst.__iter__().__next__()
l2 = lst.__iter__().__next__()
l3 = lst.__iter__().__next__()    print(l1),print(l2),print(l3)都是1

 

那么换一种方式呢?

 

lst = [1,2,3]
l1 = lst.__iter__()          从一个可迭代对象转化为迭代器
print(l1.__next__())
print(l1.__next__())
print(l1.__next__())          此时输出的结果为1,2,3,如果继续往下再加__next__(),就会报错

 

 输出可迭代对象的内存地址

 

print(str.__iter__('你好'))      <str_iterator object at 0x0000017BF45116D8>
print(list.__iter__([1,2,3]))    <list_iterator object at 0x0000017BF450B3C8>
print(dict.__iter__({'1':2}))    <dict_keyiterator object at 0x0000017BF450C4A8>
print(set.__iter__({1,2,3}))     <set_iterator object at 0x0000017BF45196C0>
print(tuple.__iter__((1,2,3)))      <tuple_iterator object at 0x0000017BF45116D8>
print(range.__iter__(range(1,5)))   <range_iterator object at 0x0000017BF4526D70>

 

 

 

生成器定义:

  通俗来说,在函数体中存在yield就是生成器,函数名+小括号就产生了生成器,并且只能向下执行

  函数体中的yield,就是辨别生成器和函数的依据

  生成器的好处就是可以节省空间,一次性完成从上往下执行

那如何产生一个生成器呢?

产生一个生成器:
def
foo(): print(123) yield 4 print(foo())      结果为,生成器foo的内存地址
print(foo)       函数foo的内存地址

  那么按照上面这个生成器来看,怎么样才能实现print(123)?

def foo():
    print(123)
    yield 456
f = foo()
print(f.__next__())    这样就实现了print(123),并有返回值456
print(foo.__next__())   如果把f换成了foo(),就会一直生成新的生成器,会重复打印123,456

yield的作用:

  yield也可以有返回值,同时也会记录生成器执行到哪里,不会再继续往下执行

  yield可以指定返回值,没有就是None

现在可以来试着捋一捋生成器的执行流程:

def foo():             1,定义函数
    print(123)          5,执行
    yield 456           6,返回值456,停止往下执行
    print(789)
    yield 1111
g = foo()              2,等号右边foo()  3,将foo()赋值给g
print(g.__next__())        4,g.__next__()

  当有大批量的数据时,用for循环就会占大量的空间,那这时不妨用生成器

li = []
def func():
    for i in range(300):
        print(i)
        li.append(i)
func()
print(li)

def func():
    for i in range(300):
        yield i
g = func()
print(g.__next__())        随取随用,不会过多的开辟空间
print(next(g))            和g.__next__()效果一样

yield和next的对应:

  一个.__next__()对应一个yield,如果多了,就会报错

def func():
    print(1)
    yield 2
    print(3)
    yield 4
    yield 5
    yield 6
g = func()
print(next(g))
print(next(g))
print(next(g))
print(next(g))        最后一个yield下面可以写代码,但是不会执行

send:发送(在外界向生成器传递参数)

  send == __next__ + 传值(传给上一个yield停住的地方)

def func():
    print(44)
    l = yield 5          send,将'哈哈'传递给l,
    print(l)
    yield 66
g = func()        # 生成一个生成器
print(g.__next__())
print(g.send('哈哈'))      输出结果为:44,5,哈哈,66

再来一个

def func():
    print(44)
    l = yield 5
    print(1)
    yield 66
g = func()
print(g.send(None))       输出结果为:44,5

  第一次启动生成器的时候不能用send,但是可以用send(None),这时send的传值功能就取消了,只保留next功能

所以,第一次启动生成器的时候,  生成器.__next__()  或者  生成器.send(None)

yield from:

def func():
    lst = [1,2,3,4,5]
    yield from lst      在这儿实现的就是for循环,for i in lst:print(i)
g = func()
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())      ps:yield from只能用next

推导式:  推导式只能走一个分支,但三元运算符可以实现多项

    先写结果,再写语句,如果有筛选,在语句后面添加条件

列表:

推导式:
    print([i for i in range(16)])    

展开式:
    li  = []
    def func():
        for i in range(16):
            li.append(i)
    func()
    print(li)

列表筛选:

推导式:
    print([i for i in range(10) if i % 3 == 0])

展开式:
    li = []
    def func():
        for i in range(10):
        if i % 3 == 0:
            li.append(i)
    func()
    print(li)

集合的推导式:

推导式:    
    dic = {'1':2,'3':4}
    print({i for i in dic.items()})         结果是:({'3':4},{'1':2})或({'1':2}{'3':4})
筛选:
    print({i for i in range(66) if i > 16})

  集合的推导式和字典很像,但是它只是集合

字典:

推导式1:
    lst1 = ['1','2']
    lst2 = [2,3]
    print({lst1[i]:lst2[i] for i in range(2)})     输出结果为{'1':2,'2':3}
推导式2:
dic
= {'1':2,'3':4} print({k:v for k,v in dic.items()})

生成器的推导式:

推导式:
    l1 = (i for i in range(1000) 条件)        print(l1),生成器的地址
    for i in range(10):
    print(l1.__next__())
展开式:
    def func():
      for i in range(100):
           if i % 3 == 0:
          yield i    
    g = func()
    for n in range(10):
      print(g.__next__())
posted @ 2019-01-14 19:34  DF-包子  阅读(145)  评论(0编辑  收藏  举报