代码改变世界

Python005-装饰器,生成器,迭代器

2018-04-18 22:56  Ashome123  阅读(184)  评论(0)    收藏  举报
一、装饰器
  1.函数即“变量”
  2.高阶函数
    把一个函数名当作实参传给另外一个函数(不修改被装饰函数代码的情况下为其添加新功能);
    返回值中包含函数名(不修改原函数的调用方式);
3.嵌套函数
    在函数体内用def定义一个函数
####装饰器一####
import time


def timer(func):                # 这一层用来传函数
    def deco(*args,**kwargs):   # 这一层用来传函数内的参数
        start_time = time.time()
        func(*args,**kwargs)
        end_time = time.time()
        print('一共用时%f秒'%(end_time-start_time))
    return deco # 不加这层则test1=timer(test1)接收不到返回值报错

@timer          # test1 = timer(test1)
def test1():
    time.sleep(1)
    print('hello,world!')

@timer
def test2(name):    # 带参数
    time.sleep(1)
    print('hello,%s!'%name)

test1()
test2('Tony')
# t = timer(test1)
# print(t())

####装饰器2####
user1 = 'aaa'
password1 = '111'
user2 = 'bbb'
password2 = '222'

def auth(person):                   # 这一层用来选角色
    def out_wrap(func):             # 这一层用来传函数
        def wrap(*args,**kwargs):   # 这一层用来传函数内的参数
            if person == 1:
                name = input('请输入用户名:')
                passwd = input('请输入密码:')

                if name == user1 and passwd == password1:
                    func(*args,**kwargs)
                else:
                    exit('账户名或密码有误!!')
            elif person == 2:
                name = input('请输入用户名:')
                passwd = input('请输入密码:')

                if name == user2 and passwd == password2:
                    func(*args, **kwargs)
                else:
                    exit('账户名或密码有误!!')
        return wrap
    return out_wrap

def home():
    print('welcome home')

@auth(person=1)
def page1():
    print('welcome to page1')

@auth(person=2)
def page2(name):
    print('welcome to page2,%s'%name)


# home()
# page1()
page2('Eason')

# 要实现不同角色进入页面打印不同名字,则需要在装饰器内部加一行打印,这个例子只是想要源代码不变且调用方式不变

二、 生成器
a = [i*2 for i in range(10)] # 列表生成式
b = (i*2 for i in range(10)) # 生成器,只能进行简单的逻辑操作
    注:b.__next__() == next(b)

1. 用函数做生成器,只需在函数里加入yield即可,可进行复杂的逻辑操作
2. 有yield时,return返回值是异常的消息,可以被e.value捕捉到
3. 通过生成器可以实现并行效果
import time

def consumer(name):
    print('%s 准备吃寿司'%name)

    while True:
        sushi = yield # 使生成器中断
        print('寿司[%s]来了,被[%s]吃了'%(sushi,name))

# c = consumer('Eason')
# c.__next__()
# b1 = '1'
# c.send(b1)

def producer(name):
    c = consumer('Tony')    # 创建一个对象,生成器不往下走
    c2 = consumer('Eason')
    c.__next__()            # 执行了这步才打印“Tony准备吃寿司”
    next(c2)                # 这句跟上面一句相同
    print('%s 准备做寿司啦!'%name)

    for i in range(5):
        time.sleep(1)
        print('\n做了2个寿司')
        c.send(i)           # 在外部把值传进生成器c,传给consumer里的变量sushi
        c2.send(i)

producer('Ashome')

三、 迭代器:python的迭代器对象表示的是一个数据流
可直接作用与for循环的对象称为可迭代对象(Iterable),直接作用与for循环的数据类型有以下几种:
    - 集合数据类型,如list,tuple,dict,set,str等
    - generator,包括生成器和带yield的generator function

可被next()调用并不断返回下一个值的对象称为迭代器(Iterator)

可用isinstance()判断是否为Iterable对象和Iterator对象:
    from collections import Iterable
    from collections import Iterator

1. 生成器是一个迭代器
2. 用iter()把list,dict,str变成迭代器
3. range()函数返回一个迭代器