'''生成器只能遍历一次的另一个例子''' # def test(): # for i in range(5): # yield i # t = test() # t1 = (i for i in t) # t2 = (x for x in t1) # print(list(t1)) # 此时t1是个生成器表达式,当利用list方法时,需要遍历生成器进行取值 # print(list(t2)) # t2的值取之于t1,但是t1的值已经被list取完了,所以此时再取t1的值时已经取不到了 ''' 一、什么是装饰器 器即函数;装饰即修饰,意指为其它函数添加新功能; 装饰器定义:本质就是函数,功能是为其它函数添加新功能 二、装饰器需要遵循的原则 1.不修改被装饰函数的源代码(开放封闭原则及) 2.为被装饰函数添加新功能后,不修改被装饰函数的调用方式 三、实现装饰器知识储备 装饰器=高阶函数+函数嵌套+闭包 ''' # 开放封闭原则:程序一旦上线以后,不应该更改程序内部的源代码;因为一旦更改了程序的源代码,并不能知道会发生什么连锁反应,其它地方可能有调用 import time # 新增需求:统计一个函数的运行时间,直接再函数内添加代码 # def cal(l): # start_time = time.time() # res = 0 # for i in l: # res += i # stop_time = time.time() # print('函数的运行时间是%s' % (stop_time-start_time)) # return res # print(cal(range(1000000))) # 利用装饰器的功能为其添加新需求 # def timmer(func): # func指向的是cal()函数地址 # def wrapper(*args, **kwargs): # start_time = time.time() # res = func(*args, **kwargs) # stop_time = time.time() # print('函数运行时间是%s' % (stop_time-start_time)) # return res # return wrapper # 返回函数名,方便指向此函数地址的cal使用cal()调用 # # @timmer # cal = timmer(cal),此时cal指向的是wrapper函数地址 # def cal(l): # res = 0 # for i in l: # res += i # return res # print(cal(range(10000000))) ''' 高阶函数定义: 1.函数接收的参数是一个函数名 2.函数的返回值是一个函数名 3.满足上述条件任意一个,都可称之为高阶函数 ''' # 高阶函数示范 # def foo(): # print('我的函数名作为参数传给高阶函数') # def gao_jie1(func): # print('我就是高阶函数1,我接收的参数名是%s' %func) # func() # 函数接收的参数是一个函数名,没有返回值,只是执行了该函数 # def gao_jie2(func): # print('我就是高阶函数2,我的返回值是%s' %func) # return func # 函数接收的参数是一个函数名,并且返回值是一个函数名 # gao_jie1(foo) # gao_jie2(foo) # 高阶函数应用1:把函数当做参数传给高阶函数 # def foo(): # print('from the foo') # def timmer(func): # start_time = time.time() # func() # stop_time = time.time() # print('函数%s 运行时间是%s' % (func, stop_time - start_time)) # timmer(foo) # 总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式 # 高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名 # def foo(): # print('from the foo') # def timmer(func): # start_time = time.time() # return func # 遇到return函数即停止了 # stop_time = time.time() # print('函数%s 运行时间是%s' % (func, stop_time - start_time)) # foo = timmer(foo) # foo() # 总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何新功能 # 利用高阶函数的特点,做到了装饰器的原则,但是却运行了原函数两次 # def foo(): # time.sleep(2) # print('from the foo') # def timmer(func): # start_time = time.time() # func() # 第一次运行原函数 # stop_time = time.time() # print('函数运行时间是 %s' % (stop_time - start_time)) # return func # 返回原函数的函数地址 # foo = timmer(foo) # 利用和原函数名相同的变量进行接受函数地址 # foo() # 第二次运行原函数 # 函数嵌套:在函数内部定义另外一个函数 # def father(name): # print('from father %s' %name) # def son(): # 函数即变量,所以这两个内部函数也算是局部变量 # print('from son') # def grandson(): # print('from grandson') # grandson() # 要运行内部函数,需要和函数所在位置为同一级;如果grandson()这个函数执行和son()函数同一级,那么会报错(NameError) # son() # father('林海峰') # 闭包:在一个作用域里放入定义变量,相当于打了一个包 # def father(name): # def son(): # # name='alex' # print('我朋友是 [%s]' %name) # def grandson(): # # name='wupeiqi' # print('我好哥们是 [%s]' %name) # grandson() # son() # father('林海峰')