迭代器和生成器

一.   迭代器

 

  1.如何查看一个数据类型的所有方法?

#dir()可以查看数据类型所有可使用的方法
print(dir([1,2]))
print(dir({1,2}))
print(dir(''))

#结果:
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__init_subclass__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

       2.通过观察我们不难发现,输出的结果里面都含有 __iter__这个方法(可迭代的都必须含有__iter__方法)

print('__iter__' in dir([1,2]))
print('__iter__' in dir({1,2}))
print('__iter__' in dir(''))



#结果:
True
True
True

  3.什么是迭代器呢?

    请看下面的例子:

r=[].__iter__()
print(r)


#结果  : <list_iterator object at 0x000001C90B547358>

  返回乐意个有‘iterator的单词,这是什么意思呢?通过百度我们明白了它就是一个迭代器,

  我们通过调用列表的__iter__方法就得到了一个迭代器。

      4.那我们再看看迭代器里面都含有什么方法

r=[].__iter__()
print(dir(r))


#['__class__', '__delattr__', '__dir__', '__doc__', 
'__eq__', '__format__', '__ge__', '__getattribute__',
'__gt__', '__hash__', '__init__', '__init_subclass__',
'__iter__', '__le__', '__length_hint__', '__lt__',
'__ne__', '__new__', '__next__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__setstate__',
'__sizeof__', '__str__', '__subclasshook__']

  这时我们发现里面有一个‘__next__'方法。那它又有什么用处呢?

L=[1,2,3,4]
r=L.__iter__()
print(r.__next__())
print(r.__next__())
print(r.__next__())
print(r.__next__())



#1
#2
#3
#4

  每调用一次__next__方法都返回一个L列表里面的值,当列表里面的值输出完时,再调用__next__方法会报错

  5,好了,通过上面的例子我们可以了解到下面知识:

      1.迭代器一定可迭代(必须含有__iter__方法)可迭代不一定就是迭代器

      2.迭代器必定含有__iter__,__next__方法

二.   生成器

    生成器时在迭代器的基础上形成的(生成器必是迭代器)

   1.生成器函数

def genteater():
    print('a')
    yield '1'


a=genteater()         #a只是一个生成器
print(a)




#<generator object genteater at 0x0000015792557048>

#generator就是生成器

  那如何打印函数里面的值呢?

def genteater():
    print('a')
    yield '1'


a=genteater()         #a只是一个生成器
print(a.__next__())   #调用__next__ 方法

#a
#1

  如果你懂了上面的例子,那么请看下面

#调用__next__方法,每次只能执行一次yield,再次调用就从上一个yield哪里开始
def genteater():
    print('a')
    yield '1'
    print('b')
    yield '2'


a=genteater()         #a只是一个生成器
print(a.__next__())   #调用__next__ 方法
print(a.__next__())   

#a
#1
#b
#2

#当然我们也可以用for循环的发放循环生成器
def genteater():
    print('a')
    yield '1'
    print('b')
    yield '2'


a=genteater()         #a只是一个生成器
for i in a:
    print(i)


#a
#1
#b
#2

  2.生成器监听文件的例子:

#监听文件
def tail(file):
    f=open(file)
    while True:
        line=f.readline()
        if line.strip():
            yield line.strip()

g=tail('xiaowu')
for i in g:
    if 'python' in i:
        print('****',i)

 

  send方法(可以向yield传值)

def generator():
    print('123')
    content=yield 'a'
    print('***',content)
    print('456')
    yield 'b'

g=generator()
print( g.__next__() )           #  ===print(g.send(None))
print(g.send('hello'))          #和next用法大致一样,只是可以在获取下一个值的时候给上一个yield的位置传值
                                #send不能用在开头
#send实例
def func(a):
    def inner(*args,**kwargs):
        ret=a(*args,**kwargs)
        ret.__next__()
        return ret
    return inner
@func
def avg():
    sum=0
    count=0
    avg=0
    while True:
        num=yield avg
        sum+=num
        count+=1
        avg=sum/count

avg_1=avg()
ret=avg_1.send(10)
ret=avg_1.send(2)
print(ret)

  生成器面试题

       

#面试题1
def a():
    for i in range(4):
        yield i

b=a()

b1=(i for i in b)
b2=(i for i in b1)
print(list(b1))          #[0,1,2,3]
print(list(b2))          #[]   (g1已经空了,b2取不到值) 


#面试题2
def add(x,y):
    return x+y

def generator():
    for i in range(4):
        yield i
g=generator()

for a in [1,10]:
    g=(add(a,b) for b in g)
print(list(g))



#[20,21,23]
#其中

for a in [1,10]:
    g=(add(a,b) for b in g)
可以被替换成如下:
a=1
g=(add(a,b) for b in g)
a=10
g=(add(a,b) for b in g) # == g=(add(a,b) for b in (add(a,b) for b in generator() ))




即可以用下列代码表示
def add(x,y):
    return x+y

def generator():
    for i in range(4):
        yield i
g=generator()

a=1
g=(add(a,b) for b in g)
a=10
g=(add(a,b) for b in g)   # == g=(add(a,b) for b in (add(a,b) for b in generator() ))
print(list(g))

 


 

        

 

posted @ 2019-05-02 20:45  寒~轩  阅读(141)  评论(0编辑  收藏  举报