第四课 函数补充--装饰器迭代器生成器匿名函数递归函数
Posted xingguang009
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第四课 函数补充--装饰器迭代器生成器匿名函数递归函数相关的知识,希望对你有一定的参考价值。
1、装饰器(补充) (在原有的函数前后增加功能,且不改变原函数的调用方式)
1.1、简单的装饰器构成:
def timer(func):
def inner(*args,**kwargs):
‘‘‘执行函数之前要做的‘‘‘
re = func(*args,**kwargs)
‘‘‘执行函数之后要做的‘‘‘
return re
return inner
def outer(flag): def timer(func): def inner(*args,**kwargs): if flag: print(‘‘‘执行函数之前要做的‘‘‘) re = func(*args,**kwargs) if flag: print(‘‘‘执行函数之后要做的‘‘‘) return re return inner return timer @outer(False) def func(): print(111) func()
1.2、设计是否生效的装饰器(加判断),在装饰器的最外层再加一层函数做判断
# 进阶的需求 # 第一种情况 # 500个函数 # 你可以设计你的装饰器 来确认是否生效 import time FLAG = True #设置的变量来判断 def outer(flag): def timmer(f): def inner(*args,**kwargs): if flag == True: start_time = time.time() ret = f(*args,**kwargs) end_time = time.time() print(end_time - start_time) else: ret = f(*args, **kwargs) return ret return inner return timmer # @outer(FLAG) # func = timmer(func) # 外层函数来判断变量 def func(a,b): print(‘begin func‘,a) time.sleep(0.1) print(‘end func‘,b) return True func(1,2)
1.3、多个装饰器的执行执行顺序:
当存在多个装饰器时,从下往上执行装饰器:
def wrapper1(func): #3 func = f def inner1(): #14 print(‘wrapper1 ,before func‘)#15 func() #16 print(‘wrapper1 ,after func‘) #17 return inner1 #4 f = inner1 def wrapper2(func): #7 func = f def inner2(): #11 print(‘wrapper2 ,before func‘) #12 func() #13 func() = f() = inner1() print(‘wrapper2 ,after func‘) #18 return inner2 #8 f = inner2 @wrapper2 #f = wrapper2 #6 #9 f = inner2 @wrapper1 #f = wrapper1 #2 #5 f = inner1 def f(): #1 print(‘in f‘) #16 f() #走到这步时才真正的开始执行函数 #10 真正开始执行,按顺序往回找:这时 f() = inner2()
在执行函数之前,先进行装饰器的加载。
执行结果:
wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func
总结:后执行的放在上面,先执行的放在下面
# # 装饰器 登录 记录日志 # import time # login_info = {‘alex‘:False} # def login(func): # manager # def inner(name): # if login_info[name] != True: # user = input(‘user :‘) # pwd = input(‘pwd :‘) # if user == ‘alex‘ and pwd == ‘alex3714‘: # login_info[name] = True # if login_info[name] == True: # ret = func(name) # timmer中的inner # return ret # return inner # # def timmer(f): # def inner(*args,**kwargs): # start_time = time.time() # ret = f(*args,**kwargs) # 调用被装饰的方法 # end_time = time.time() # # print(end_time - start_time) # return ret # return inner # # @login # @timmer # def index(name): # print(‘欢迎%s来到博客园首页~‘%name) # # @login # @timmer # manager = login(manager) # def manager(name): # print(‘欢迎%s来到博客园管理页~‘%name) # # index(‘alex‘) # index(‘alex‘) # manager(‘alex‘) # manager(‘alex‘)
2、迭代器和生成器:
2.1、可迭代、迭代器:(Iterable,Iterator)
可迭代:可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了__iter__方法(凡是可以使用for循环取值的都是可迭代的)
可迭代的类型:列表 字典 元组 字符串 集合 range 文件句柄 enumerate
迭代器:迭代器 = iter(可迭代的)或者li.__iter__(),自带一个__next__方法
l = [1,2,3] # lst_iter = iter(l) # l.__iter__() # while True: # try: # print(next(lst_iter)) # lst_iter.__next__() # except StopIteration: # break
# py2 range 不管range多少 会生成一个列表 这个列表将用来存储所有的值
# py3 range 不管range多少 都不会实际的生成任何一个值
# 迭代器的优势:
# 节省内存
# 取一个值就能进行接下来的计算 ,而不需要等到所有的值都计算出来才开始接下来的运算 —— 快
# 迭代器的特性:惰性运算
# f = open()
# for line in f: 可迭代的
2.2、生成器:
1、自己写的迭代器 就是一个生成器
2、两种自己写生成器(迭代器)的机制:生成器函数 生成器表达式
3、简单生成器的写法:(关键字yield)
# 凡是带有yield的函数就是一个生成器函数
# def func():
# print(‘****‘)
# yield 1
# print(‘^^^^‘)
# yield 2 # 记录当前所在的位置,等待下一次next来触发函数的状态
#
# g = func() #调用后代码未执行,返回一个生成器(迭代器)
# print(‘--‘,next(g))
# print(‘--‘,next(g))
# 生成器函数的调用不会触发代码的执行,而是会返回一个生成器(迭代器)
# 想要生成器函数执行,需要用next或for
# 使用生成器监听文件输入的例子 # import time # def listen_file(): # with open(‘userinfo‘) as f: # while True: # line = f.readline() # if line.strip(): # yield line.strip() # time.sleep(0.1) # # g = listen_file() # for line in g: # print(line)
4、生成器中的关键字send
# send关键字 # def func(): # print(11111) # ret1 = yield 1 #ret1 接受secd传入进来的值 # print(22222,‘ret1 :‘ret1) # ret2 = yield 2 # print(33333,‘ret2 :‘,ret2) # yield 3 # # g = func() # ret = next(g) # print(ret) # print(g.send(‘alex‘)) # 在执行next的过程中 传递一个参数 给生成器函数的内部 # print(g.send(‘金老板‘)) # 想生成器中传递值 有一个激活的过程 第一次必须要用next触发这个生成器
# 例子 # 计算移动平均值 # 12 13 15 18 # 月度 的 天平均收入 # def average(): # sum_money = 0 # day = 0 # avg = 0 # while True: # money = yield avg # sum_money += money # day += 1 # avg = sum_money/day # # g = average() # next(g) # print(g.send(200)) # print(g.send(300)) # print(g.send(600))
5、预激生成器
# def init(func):
# def inner(*args,**kwargs):
# ret = func(*args,**kwargs)
# next(ret) # 预激活
# return ret
# return inner
#
# @init
# def average():
# sum_money = 0
# day = 0
# avg = 0
# while True:
# money = yield avg
# sum_money += money
# day += 1
# avg = sum_money/day
#
# g = average()
# print(g.send(200))
# print(g.send(300))
# print(g.send(600))
6、yield from
# def generator_func(): # yield from range(5) # yield from ‘hello‘ # # for i in range(5): # yield i # for j in ‘hello‘: # yield j # g = generator_func() # for i in generator_func(): # print(i) # g1 = generator_func() # g2 = generator_func() # next(generator_func()) # next(generator_func())
7、如何从生成器中取值
# 第一种 :next 随时都可以停止 最后一次会报错 # print(next(g)) # print(next(g)) # 第二种 :for循环 从头到尾遍历一次 不遇到break、return不会停止 # for i in g: # print(i) # 第三种 :list tuple 数据类型的强转 会把所有的数据都加载到内存里 非常的浪费内存 # print(g) # print(list(g))
8、特性
# 生成器函数 是我们python程序员实现迭代器的一种手段 # 主要特征是 在函数中 含有yield # 调用一个生成器函数 不会执行这个函数中的带码 只是会获得一个生成器(迭代器) # 只有从生成器中取值的时候,才会执行函数内部的带码,且每获取一个数据才执行得到这个数据的带码 # 获取数据的方式包括 next send 循环 数据类型的强制转化 # yield返回值的简便方法,如果本身就是循环一个可迭代的,且要把可迭代数据中的每一个元素都返回 可以用yield from # 使用send的时候,在生成器创造出来之后需要进行预激,这一步可以使用装饰器完成 # 生成器的特点 : 节省内存 惰性运算 # 生成器用来解决 内存问题 和程序功能之间的解耦
3、列表推倒式
# new_lst = [] # for i in range(10): # new_lst.append(i**2) # print(new_lst) # print([i**2 for i in range(10)]) # l = [1,2,3,-5,6,20,-7] # print([i%2 for i in range(10)]) # l = [1,2,3,-5,6,20,-7] # print([num for num in l if num%2 == 1]) # 30以内所有能被3整除的数 # print([i for i in range(30) if i%3 ==0]) # # 30以内所有能被3整除的数的平方 # print([i**2 for i in range(30) if i%3 ==0]) # 找到嵌套列表中名字含有两个‘e’的所有名字 # names = [[‘Tom‘, ‘Billy‘, ‘Jefferson‘, ‘Andrew‘, ‘Wesley‘, ‘Steven‘, ‘Joe‘], # [‘Alice‘, ‘Jill‘, ‘Ana‘, ‘Wendy‘, ‘Jennifer‘, ‘Sherry‘, ‘Eva‘]] # print([name for name_lst in names for name in name_lst if name.count(‘e‘) == 2])
4、生成器表达式:
# l = [i for i in range(30) if i%3 ==0] # 列表推倒式 排序的时候 # g = (i for i in range(30) if i%3 ==0) # 生成器表达式 庞大数据量的时候 使用生成器表达式 # print(l) # print(g) # for i in g:print(i)
5、内置函数:(总共有68个内置函数)
6、匿名函数:
# lambda表达式 # def add(a,b): # return a+b
# add = lambda a,b : a+b 传两个参数 : 执行的方法
# print(add(1,2))
# # for i in map(func,range(10)):print(i)
# for i in map(lambda num : num ** 2 ,range(10)):print(i)
# def func(num): # return num%2 # print(min(-2,3,-4,key=func)) 可以直接执行执行方式 # print(min(-2,3,-4,key=lambda num:num%2))
7、递归函数:
# 递归 就是自己调用自己
# def func(): # print(1) # func() # # func() # 997 /998
# 递归需要有一个停止的条件
# def fn(6):
# if 6 == 1:return 1
# return 6*fn(5)
# print(fn(6))
以上是关于第四课 函数补充--装饰器迭代器生成器匿名函数递归函数的主要内容,如果未能解决你的问题,请参考以下文章
20181130(装饰器补充,叠加多个装饰器,有参装饰器,三元表达式,生成式,匿名函数,内置函数)
装饰器的补充(叠加多个装饰器,有参装饰器,三元表达式,生成式,匿名函数)
python学习第四天,列表生产式,匿名函数,生成器,内置函数,迭代器,装饰器,json和pickle的序列化和反序列化