9.迭代器、生成器与装饰器

class Myrange(object):
    def __init__(self,n):
        self.idx=0
        self.n=n

    def __iter__(self):
        return self

    def __next__(self):
        if self.idx<self.n:
            val = self.idx
            self.idx+=1
            return val
        else:
            raise StopIteration()
myrange = Myrange(3)
print(next(myrange))#0
#next()自动调用__iter__(),发现返回自身,自身作为参数,再自动调用__next__(),return val的值给next()函数
for i in myrange:
    #for…in…会反复调用next()
    print(i)
for i in myrange:
    #如果一个可迭代对象同时它的迭代器又是它本身的话会导致无法重复迭代(迭代器)
    print(i)
"""
1
2
"""

 

#iter(iterable)
list1 = [1,2,3]
#print(next(list1))
#TypeError: 'list' object is not an iterator
list_iter = iter(list1)
print(list_iter)#<list_iterator object at 0x000001D3C5678518>

next(list_iter)
for i in list_iter:
    print(i)
#next(list_iter)#StopIteration
for i in list_iter:#一个可迭代对象同时它的迭代器又是它本身,无法重复迭代
    print(i)
#iter(callable,sentinel)
#callable:许多Python对象都是我们所说的可调用的,即是任何通过函数操作符()来调用的对象。
# Python有4中可调用对象:函数,方法,类,以及一些类的实例
#第一个参数一般为函数,等于第二个参数为迭代停止条件

def used_iter(x=0):
   x+=1
   return x

for i in iter(used_iter,8):
    print(i)
"""
无限输出1,1,1……
"""
class count():
    def __init__(self,x=0):
        self.x=x
count = count()

def used_iter():
   count.x+=3
   return count.x

for i in iter(used_iter,8):
    print(i)
"""
3
6
9
12
15
……
无限输出
"""
global x
x=0
def used_iter():
   x+=1
   return x

for i in iter(used_iter,8):
    print(i)
    #UnboundLocalError: local variable 'x' referenced before assignment
class count():
    def __init__(self,x=0):
        self.x=x
count = count()

def used_iter():
   count.x+=1
   return count.x

for i in iter(used_iter,3):
    print(i)
"""
1
2
"""

 

class Zrange():
    def __init__(self,n):
        self.n=n
    def __iter__(self):
        return ZrangeIterator(self.n)

class ZrangeIterator():
    def __init__(self, n):
        self.i = 0
        self.n = n

    def __iter__(self):
        return self

    def __next__(self):
        if self.i < self.n:
            i = self.i
            self.i += 1
            return i
        else:
            raise StopIteration()

zrange = Zrange(3)

print([i for i in zrange])
print([i for i in zrange])

g  = iter([1,2,3])#可迭代对象同时它的迭代器又是它本身
#iter(obj)用于返回迭代器实例,obj是可迭代对象,即该对象必须实现__iter__方法;
#事实上iter函数与__iter__方法联系非常紧密,iter()是直接调用该对象的__iter__(),
#并把__iter__()的返回结果作为自己的返回值,故该用法常被称为“创建迭代器”。
for i in g:
    print(i)
for i in g:
    print(i)

g=(x for x in range(2))#可迭代对象同时它的迭代器又是它本身
for i in g:
    print(i)
for i in g:
    print(i)

 

1.迭代器

迭代器表面看是一个数据流,依次取数据,直至取完,而且数据不会重复利用(可迭代对象可以)。

import itertools
for i in itertools.product("wc","zq","a"):
    print(i)
    
"""
#itertools模块提供近20个迭代器工具函数
('w', 'z', 'a')
('w', 'q', 'a')
('c', 'z', 'a')
('c', 'q', 'a')
"""

 

class Myrange(object):
    def __init__(self):
        self.idx=0


    def __iter__(self):
        return self

    def __next__(self):
            val = self.idx+1
            return val
my = Myrange()
for i in my:
    print(i)
#永远输出1,不会停止

 

def triangles():
    L=[1]
    while True:
        yield L

        L=[1]+[L[i]+L[i+1] for i in range(len(L)-1)]+[1]

n=0
results = []
for t in triangles():
    print(t)
    results.append(t)
    n = n + 1
    if n == 10:
        break
if results == [
    [1],
    [1, 1],
    [1, 2, 1],
    [1, 3, 3, 1],
    [1, 4, 6, 4, 1],
    [1, 5, 10, 10, 5, 1],
    [1, 6, 15, 20, 15, 6, 1],
    [1, 7, 21, 35, 35, 21, 7, 1],
    [1, 8, 28, 56, 70, 56, 28, 8, 1],
    [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
]:
    print('测试通过!')
else:
    print('测试失败!')

 

def myYield(n):
    while n>0:
        print("开始生产:{}".format(n))
        yield n
        print()
        print("结束生产:{}".format(n))

        n-=1
for i in myYield(3):
    print(i)
"""
开始生产:3
3

结束生产:3
开始生产:2
2

结束生产:2
开始生产:1
1

结束生产:1
"""
my = myYield(3)
print(my.__next__())
my.__next__()
"""
开始生产:3
3

结束生产:3
开始生产:2
"""
def myYield(n):
    while n>0:
        rcv = yield n
        print(rcv)
        n-=1
my = myYield(4)
#my.send("a"),第一次调用,仅仅yield n 就停止了,第二次调用时才可以把值赋给rcv
#TypeError: can't send non-None value to a just-started generator
print(my.send(None))
print(my.send("a"))
"""
4
a
3
"""
def myYield(n):
    while n>0:
        rcv = yield n
        print(rcv)
        if rcv =="a":
            n=5
        n-=1
my = myYield(4)
#my.send("a"),第一次调用,仅仅yield n 就停止了,第二次调用时才可以把值赋给rcv
#TypeError: can't send non-None value to a just-started generator
print(my.send(None))
print(my.send("a"))
for i in my:
    print(i)
"""
4
a
4
None
3
None
2
None
1
None
"""
def first():
    print("任务1完成")

def second():
    print("任务2完成")

def third():
    print("任务3完成")

def consumer():
    print("wait for assisment")
    while True:
        data = yield
        if data == 0:
            first()
        elif data == 1:
            second()
        else:
            third()

def producer():
    c=consumer()
    c.__next__()
    for i in range(3):
        print("发送{}".format(i))
        c.send(i)

producer()

#生成器的send()解决了生产者与消费者的并发与同步问题

 

装饰器:

(1)本质:装饰器的本质是函数,其基本语法都是用关键字def去定义的。

(2)功能:装饰其他函数,即:为其他函数添加附加功能。

(3)原则:不能修改被装饰的函数的源代码,不能修改被装饰的函数的调用方式。即:装饰器对待被修饰的函数是完全透明的。
import functools

def log(text):
    def decorator(func):
        #@functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

@log("execute")
def now():
    print('2015-3-25')

now()
print(now.__name__)

def abc(n):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args,**kw):
            if n>10:
                return func(*args,**kw)
            else:
                print("小于等于10")
        return wrapper

    return decorator
@abc(11)
def add(a,b):
    return a+b

print(add(1,2))
import time
def m(fn):
    def wrapper(*args,**kw):
        start=time.time()
        a=fn(*args,*kw)
        finish = time.time()
        return finish-start,a
    return wrapper
@m
def fast(x,y):
    time.sleep(5)
    return x+y
f= fast(11,22)
print(f)

 

posted on 2019-02-26 21:45  wzc521  阅读(95)  评论(0)    收藏  举报

导航