import time def timer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return res return wrapper @timer #把@timer放到foo()函数的定义处,至关于执行了foo=timer(foo) def foo(): time.sleep(3) print('from foo') foo() """执行结果 from foo run time is 3.000171661376953 """
def timer2(ms = 'file'): def timer(func): def wrapper(*args, **kwargs): if ms == 'file': name = 'file_name' res = func(*args, **kwargs) print('%s login successful'%name) return res elif ms == 'mysql': name = 'mysql_name' res = func(*args, **kwargs) print('%s login successful'%name) return res else: name = 'other_name' res = func(*args, **kwargs) print('%s login successful'%name) return res return wrapper return timer @timer2(ms = 'file') #timer2(ms = 'file')返回timer函数引用 就和无参的同样了 def foo(name): print('from foo %s'%name) foo('rose') """ from foo rose file_name login successful """
# 叠加多个装饰器 # 1. 加载顺序(outter函数的调用顺序):自下而上 # 2. 执行顺序(wrapper函数的执行顺序):自上而下 def outter1(func1): # func1=wrapper2的内存地址 print('加载了outter1') def wrapper1(*args, **kwargs): print('执行了wrapper1') res1 = func1(*args, **kwargs) return res1 return wrapper1 def outter2(func2): # func2=wrapper3的内存地址 print('加载了outter2') def wrapper2(*args, **kwargs): print('执行了wrapper2') res2 = func2(*args, **kwargs) return res2 return wrapper2 def outter3(func3): # func3=最原始的那个index的内存地址 print('加载了outter3') def wrapper3(*args, **kwargs): print('执行了wrapper3') res3 = func3(*args, **kwargs) return res3 return wrapper3 # 被装饰函数的正上方,单独一行 @outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址 @outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址 @outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址 def index(): # index=outter1(outter2(outter3(index))) print('from index') print('==========================') index() """ 加载了outter3 加载了outter2 加载了outter1 ========================== 执行了wrapper1 执行了wrapper2 执行了wrapper3 from index """
对于序列类型:字符串、列表、元组,咱们可使用索引的方式迭代取出其包含的元素。但对于字典、集合、文件等类型是没有索引的,若还想取出其内部包含的元素,则必须找出一种不依赖于索引的迭代方式,这就是迭代器,迭代器有节省内存的好处。mysql
可迭代对象指的是内置有__iter__方法的对象,即obj.__iter__,以下sql
""" #优势: - 提供一种统一的、不依赖于索引的迭代方式 - 惰性计算,节省内存 #缺点: - 没法获取长度(只有在next完毕才知道到底有几个值) - 一次性的,只能日后走,不能往前退,迭代完,就不能再次迭代 """ dic={'a':1,'b':2,'c':3} iter_dic=dic.__iter__() #获得迭代器对象,迭代器对象即有__iter__又有__next__ 迭代器对象.__iter__()后仍然是迭代器对象自己 print(iter_dic) #<dict_keyiterator object at 0x0000000000BA99F8> print(iter_dic.__iter__()) #<dict_keyiterator object at 0x0000000000BD99F8> print(iter_dic.__iter__() is iter_dic) #True 迭代器对象.__iter__()后仍然是迭代器对象自己 print(iter_dic.__next__()) #等同于next(iter_dic) print(iter_dic.__next__()) #等同于next(iter_dic) print(iter_dic.__next__()) #等同于next(iter_dic) # print(iter_dic.__next__()) #抛出异常StopIteration,或者说结束标志 #有了迭代器,咱们就能够不依赖索引迭代取值了 iter_dic=dic.__iter__() while 1: try: k=next(iter_dic) print(k,dic[k]) except StopIteration: # 须要咱们本身捕捉异常 break #基于for循环,咱们能够彻底再也不依赖索引去取值了 dic={'a':1,'b':2,'c':3} for k in dic: print(k, dic[k]) print('123123213') for k in dic: print(k, dic[k]) #for循环的工做原理 #1:执行in后对象的dic.__iter__()方法,获得一个迭代器对象iter_dic #2: 执行next(iter_dic),将获得的值赋值给k,而后执行循环体代码 #3: 重复过程2,直到捕捉到异常StopIteration,结束循环
dir([1,2].__iter__())#是列表迭代器中实现的全部方法, dir([1,2]) #是列表中实现的全部方法,都是以列表的形式返回,为了看的更清楚,分别把他们转换成集合,而后取差集。 # print(dir([1,2].__iter__())) # 返回一个列表 # print(dir([1,2])) print(set(dir([1,2].__iter__()))-set(dir([1,2]))) #{'__length_hint__', '__next__', '__setstate__'} #列表迭代器中多了三个方法 iter_l = [1,2,3,4,5,6].__iter__() #获取迭代器中元素的长度 print(iter_l.__length_hint__()) #6 #根据索引值指定从哪里开始迭代 print('*',iter_l.__setstate__(4)) #* None #一个一个的取值 print('**',iter_l.__next__()) #** 5 print('***',iter_l.__next__()) #*** 6 print('__next__' in dir(range(12))) #False print('__iter__' in dir(range(12))) #True from collections import Iterator print(isinstance(range(100000000),Iterator)) # False 验证range执行以后获得的结果不是一个迭代器
from collections import Iterable,Iterator class Foo: def __init__(self,start): self.start=start def __iter__(self): return self def __next__(self): return 'aSB' f=Foo(0) print(isinstance(f,Iterable)) #True 可迭代 print(isinstance(f,Iterator)) #True 迭代器
""" 生成器表达式: 优势:省内存,一次只产生一个值在内存中 把列表推导式的[]换成()就是生成器表达式 """ gen_exp = (i for i in range(10)) #生成器表达式 print(gen_exp) #<generator object <genexpr> at 0x0000000000A1DEB8> # for i in gen_exp: #取出生成器表达式的值,for循环 # print(i) print(gen_exp.__next__()) #next方法 print(gen_exp.__next__()) print(gen_exp.__next__())
egg_list=['鸡蛋%s' %i for i in range(10)] #列表解析 print(egg_list) #['鸡蛋0', '鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4', '鸡蛋5', '鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9'] laomuji=('鸡蛋%s' %i for i in range(10))#生成器表达式 print(laomuji) #<generator object <genexpr> at 0x0000000000BA3938> print(next(laomuji)) #鸡蛋0 next本质就是调用__next__ print(laomuji.__next__()) #鸡蛋1 print(next(laomuji)) #鸡蛋2 #sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,因此,能够直接这样计算一系列值的和: print(sum([x ** 2 for x in range(4)])) #14 #而不用画蛇添足的先构造一个列表: print(sum(x ** 2 for x in range(4))) #14 ################################### def demo(): for i in range(4): yield i g=demo() g1=(i for i in g) g2=(i for i in g1) print(list(g1),type(g1)) #[0, 1, 2, 3] <class 'generator'> print(list(g2)) #[] ################################### def demo(): for i in range(4): yield i g=demo() g1=[i for i in g] g2=(i for i in g1) print(list(g1),type(g1)) #[0, 1, 2, 3] <class 'list'> print(list(g2)) #[0, 1, 2, 3] print(list(g2)) #[]
""" 生成器函数: 只要函数内部包含有yield关键字,那么函数名()的到的结果就是生成器,而且不会执行函数内部代码 生成器就是迭代器(执行函数获得生成器) """ def product(): for i in range(1, 3): print("开始生产包子") yield "第 %d 屉包子" % (i) print("卖包子,买完再生产") pro = product() # 生成一个作包子的生成器,至关于作包子的 print(pro) p = print(pro.__next__()) # 卖包子的 print('===') print(pro.__next__()) print('============') for i in pro: print(i) """ <generator object product at 0x00000000006DDEB8> 开始生产包子 第 1 屉包子 === 卖包子,买完再生产 开始生产包子 第 2 屉包子 ============ 卖包子,买完再生产 """ def product(): for i in range(1,3): print("开始生产包子") yield "第 %d 屉包子" %(i) print("卖包子,买完再生产") pro = product() #生成一个作包子的生成器,至关于作包子的 while 1: try: k=next(pro) print(k) except StopIteration: # 须要咱们本身捕捉异常 break
#生成器函数 def my_range(): print('我是一个生成器函数') n = 0 while 1: yield n n += 1 #实现开始和结束 def my_range2(start, stop): n = start while n < stop: yield n n += 1 #再进一步,实现步长: def my_range3(start, stop, step): n = start while n < stop: yield n n += step #生成器本质上就是个迭代器,咱们根据本身的想法创造的迭代器,它固然也支持for循环: for i in my_range3(1, 10, 2): print(i)
import time def tail(filename): f = open(filename) f.seek(0, 2) #从文件末尾算起 while True: line = f.readline() # 读取文件中新的文本行 if not line: time.sleep(0.1) continue yield line tail_g = tail('tmp') for line in tail_g: print(line)
def gen1(): for c in 'AB': yield c for i in range(3): yield i print(gen1()) #['A', 'B', 0, 1, 2] def gen2(): yield from 'AB' yield from range(3) print(list(gen2())) #['A', 'B', 0, 1, 2]
import pickle class Course: def __init__(self,name,price,period,teacher): self.name = name self.price = price self.period = period self.teacher = teacher def get_course(): with open('course_info', 'rb') as f: while True: try: course_obj = pickle.load(f) yield course_obj except EOFError: break cour=get_course() print(cour) print(cour.__iter__()) print(cour.__next__()) print(cour.__next__()) for obj in cour: print(obj.name) ############################ def get_line(): with open('a.txt', encoding='utf-8', mode='r') as f: while True: try: line = f.readline() yield line except StopIteration: break g=get_line() print(g) print(g.__next__()) print(g.__next__()) print(g.__next__())
""" 协程函数: yield关键字的另一种使用形式:表达式形式的yield 对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g) yield总结 一、把函数作成迭代器 二、对比return,能够返回屡次值,能够挂起/保存函数的运行状态 """ def eater(name): print('%s 准备开始吃饭啦' % name) food_list = [] for i in range(4): food = yield food_list print('%s 吃了 %s' % (name, food)) food_list.append(food) print('while', food_list) # print('eater',food_list) ####这的代码不会执行,尚未走到这程序就退出了 g = eater('tom') print(g) g.send(None) # 对于表达式形式的yield,在使用时,第一次必须传None,g.send(None)等同于next(g) print('====') g.send('包子') g.send('米饭') g.send('面条') try: g.send('稀饭') except StopIteration: g.close() #依旧执行后面的print(g) # quit() #后面的print(g)就不执行了 try: g.send('肉夹馍') except StopIteration: g.close() print(g) """ <generator object eater at 0x0000000000BA1BF8> tom 准备开始吃饭啦 ==== tom 吃了 包子 while ['包子'] tom 吃了 米饭 while ['包子', '米饭'] tom 吃了 面条 while ['包子', '米饭', '面条'] tom 吃了 稀饭 while ['包子', '米饭', '面条', '稀饭'] <generator object eater at 0x0000000000BA1BF8> """ # 单线程一边发送,一边执行 import time def consumer(name): print("%s 准备吃包子啦!" % name) while True: food = yield print("包子[%s]来了,被[%s]吃了!" % (food, name)) def producer(name): c = consumer('顾客A') c2 = consumer('顾客B') c.__next__() c2.__next__() print("老板%s==开始准备作包子啦!" % name) for i in range(3): time.sleep(1) print("作了2个包子!") c.send(i) # 发送的值,就是yield的返回值 c2.send(i) producer("tom") print('===========') producer("jack") """ 顾客A 准备吃包子啦! 顾客B 准备吃包子啦! 老板tom==开始准备作包子啦! 作了2个包子! 包子[0]来了,被[顾客A]吃了! 包子[0]来了,被[顾客B]吃了! 作了2个包子! 包子[1]来了,被[顾客A]吃了! 包子[1]来了,被[顾客B]吃了! 作了2个包子! 包子[2]来了,被[顾客A]吃了! 包子[2]来了,被[顾客B]吃了! =========== 顾客A 准备吃包子啦! 顾客B 准备吃包子啦! 老板jack==开始准备作包子啦! 作了2个包子! 包子[0]来了,被[顾客A]吃了! 包子[0]来了,被[顾客B]吃了! 作了2个包子! 包子[1]来了,被[顾客A]吃了! 包子[1]来了,被[顾客B]吃了! 作了2个包子! 包子[2]来了,被[顾客A]吃了! 包子[2]来了,被[顾客B]吃了! """
# def eat(name): # print('%s要开始吃了!' % name) # while 1: # food = yield # print('{}在吃{}'.format(name, food)) # # # a = eat('alex') # a.__next__() # 初始化,让函数暂停在yield处 # a.send('包子') # send两个做用:1.给yield传值 2.继续执行函数 # a.send('饺子') def init(func): #在调用被装饰生成器函数的时候首先用next激活生成器 def inner(*args,**kwargs): g = func(*args,**kwargs) next(g) return g return inner @init def averager(): total = 0.0 count = 0 average = None while True: term = yield average total += term count += 1 average = total/count g_avg = averager() # next(g_avg) 在装饰器中执行了next方法 print(g_avg.send(10)) #10.0 print(g_avg.send(30)) #20.0 print(g_avg.send(5)) #15.0