1、装饰器:
定义: python装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象(函数的指针)
属性特点:
实质: 是一个函数
参数:是你要装饰的函数名(并非函数调用)
返回:是装饰完的函数名(也非函数调用)
作用:为已经存在的对象添加额外的功能
特点:不需要对对象做任何的代码上的变动
应用场景:装饰器最大的作用就是对于我们已经写好的程序,我们可以抽离出一些雷同的代码组建多个特定功能的装饰器,这样我们就可以针对不同的需求去使用特定的装饰器,这时因为源码去除了大量泛化的内容而使得源码具有更加清晰的逻辑。
import time def timer(func): def deco(): start = time.time() res=func() stop = time.time() print(stop-start) return res #print(deco) return deco @timer #time01 = timer(time01) def time01(): time.sleep(2) print('test is running') return '------test001' #time01 = timer(time01) #print(time01)#deco内存地址 print(time01())
#装饰函数带参数: import time def add_timer(func): def wanner(a,b): start_time = time.time() func(a,b) stop_time = time.time() print('运行时间%s'%(stop_time-start_time)) return wanner @add_timer # add = add_timer(add) def add(a,b): time.sleep(2) print('求和%s'%(a+b)) add(3,5)
#装饰函数带不定长参数: import time def add_timer(func): def wanner(*args,**kwargs): start_time = time.time() func(*args,**kwargs) stop_time = time.time() print('运行时间%s'%(stop_time-start_time)) return wanner @add_timer # add = add_timer(add) def add(*args,**kwargs): time.sleep(2) sum = 0 for i in args: sum+=i print('求和%s'%sum) add(3,5,4,5,6,7)
#带参数的装饰器: import time def timer(parameter): def out_wanner(func): def wanner(*args,**kwargs): if parameter == 'task1': start_time = time.time() res = func(*args,**kwargs) stop_time = time.time() print('the task1 run time is%s'%(stop_time-start_time)) return res elif parameter == 'task2': start_time = time.time() res = func(*args,**kwargs) stop_time = time.time() print('the task2 run time is%s'%(stop_time-start_time)) return res return wanner return out_wanner @timer(parameter='task1')#task1 = timer(task1) task1=timer(task1) def task1(): time.sleep(2) print("in the task1") return '-------test01' @timer(parameter='task2') def task2(): time.sleep(2) print("in the task2") return '-------test02' print(task1()) print(task2())
2、生成器generator:
定义:创建python迭代器的过程虽然强大,但是很多时候使用不方便。生成器是一个简单的方式来完成迭代。简单来说,Python的生成器是一个返回可以迭代对象的函数。
实现方法:
1、要创建一个generator,有很多种方法,第一种方法很简单,只有把一个列表生成式的[]中括号改为()小括号,就创建一个generator
2、在一个一般函数中使用yield
关键字,可以实现一个最简单的生成器,此时这个函数变成一个生成器函数。yield
与return
返回相同的值,区别在于return
返回后,函数状态终止,而yield
会保存当前函数的执行状态,在返回后,函数又回到之前保存的状态继续执行。
生成器函数与一般函数的不同点:
-
-
- 生成器函数包含一个或者多个
yield
- 像
__iter__()
和__next__()
方法等是自动实现的,所以我们可以通过next()
方法对对象进行迭代 - 一旦函数被
yield
,函数会暂停,控制权返回调用者 - 局部变量和它们的状态会被保存,直到下一次调用
- 函数终止的时候,
StopIteraion
会被自动抛出
- 生成器函数包含一个或者多个
-
genertor_list = [1,2,34,5,6,7,5,44,3,2,24,6] print(type(genertor_list))#列表 #列表生成式 genertor_list01 = [x+1 for x in genertor_list] print(genertor_list01) #生成器 genertor_list02 = (x+1 for x in genertor_list) print(genertor_list02) #第一种生成器取值方法 print(next(genertor_list02)) #第二种生成器取值方法 for i in genertor_list02: print(i)
#菲波那切 # list01 = [] # def feibo(n): # i = 0 # a,b=0,1 # while i < n: # list01.append(b) # a,b = b, a+b # i+=1 # return 'done' # feibo(10) #print(list01) #生成器函数 def fib(max): n,a,b =0,0,1 while n < max: yield b a,b =b,a+b n = n+1 return 'done' #print(fib(10)) # a=fib(10) # print(a.__next__()) # print(a.__next__()) # print('-----test01') # print(a.__next__()) for i in fib(6): print(i)
#但是用for循环调用generator时,发现拿不到generator的return语句的返回值。 # 如果想要拿到返回值, # 必须捕获StopIteration错误,返回值包含在StopIteration的value中: g = fib(6) while True: try: x = next(g) print('g:%d'%x) except StopIteration as e: print("genertor return value:%s"%e.value) break
应用:单线程下并发
#生产者&消费者模型 ''' 单线程一般是串行分开执行程序 而yield的特性,打破了这一约束,使得我们在单线程编程的过程中,依然可以实现异步并发 ''' #这段功能实现了异步IO的雏形,也是一个简单的协程处理方式。 import time def consumer(name): print('%s准备吃烧烤了'%name) while True: shaokao = yield print("烧烤%s被%s吃了!" %(shaokao,name) ) def producer(): A = consumer('张飞') B = consumer('刘备') A.__next__() B.__next__() print('开始生火准备烤肉。。。') for i in range(3): time.sleep(2) A.send('茄子') B.send('鸡腿') producer()
3、迭代器iterator
定义:可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
特点:
1、访问者不需要关心迭代器内部结构,只需不断执行next()方法获取下一个内容;
2、不能随机访问集合中的某个值,只能从头到尾顺序的读取;
3、访问到一半时不能回退,不能访问之前的值;
4、适合遍历很大的数据集合,节省内存,提升速度。
使用迭代器不要求事先准备好整个迭代过程中的所有元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后元素可以不存在或者被销毁。因此迭代器适合遍历一些数量巨大甚至无限的序列。
小结
凡是可作用于for
循环的对象都是Iterable
类型;
凡是可作用于next()
函数的对象都是Iterator
类型,它们表示一个惰性计算的序列;
集合数据类型如list
、dict
、str
等是Iterable
但不是Iterator
,不过可以通过iter()
函数获得一个Iterator
对象。
#判断可迭代对象 #可以使用isinstance()判断一个对象是否是Iterator对象 from collections import Iterator # print( isinstance([],Iterator)) # print( isinstance({},Iterator)) # print( isinstance("adb",Iterator)) # print( isinstance((x+1 for x in range(10)),Iterator)) '''生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。 把list、dict、str等Iterable变成Iterator可以使用iter()函数:''' print(iter([]),Iterator) it = iter([1, 2, 3, 4, 5]) print(type(it)) while True: try: x=next(it) print(x) except StopIteration: break