python——装饰器,迭代器,生成器
一、装饰器:
定义:本质是函数,为其他函数添加附加功能
原则:不能修改被装饰的函数的源代码和调用方式
实现装饰器的知识储备:
1.函数就是“变量”
2.高阶函数
- 把一个函数名(门牌号相当于内存地址)当做实参传给另一个函数
- 返回值必须包含函数名
3.函数嵌套(闭包):在函数体内用def声明一个函数
1 def foo(): 2 print('in the foo') 3 def bar(): 4 print('in the bar') 5 6 bar() #必须要调用这个函数才能运行内部的函数,所以在装饰器中必须要return内部的函数名称才能调用 7 foo()
高阶函数 + 嵌套函数 = 装饰器
1 import time
2
3 def timer(func):
4 def doc(*args,**kwargs):
5 start_time=time.time()
6 func(*args,**kwargs)
7 stop_time=time.time()
8 print("运行耗时%s"%(stop_time-start_time))
9 return doc
10
11 @timer #==不需要修改调用方式,直接走装饰器里面的函数,来达到增加功能的作用
12 def test1():
13 time.sleep(3)
14 print("in the test1")
15
16 @timer
17 def test2(*args,**kwargs):
18 print("test2:",*args,**kwargs)
19
20
21 test1()
22 test2("alex",[1,2,3,4],{"alex":[15,51,"scinjks"],"yjx":15})
return值的问题
1 username,password="alex","abc123" 2 def auth(func): 3 def doc(*args,**kwargs): 4 user_input_username=input("请输入用户名:") 5 user_input_password=input("请输入密码:") 6 if user_input_username==username and user_input_password==password: 7 func(*args,**kwargs) #=运行下面的那个函数的返回值,so要return这个返回值到doc的函数。。实际上经过这一串操作。home()=doc() 8 print("welcom back %s"%user_input_username) 9 return func(*args,**kwargs) 10 else: 11 exit() 12 13 return doc 14 15 def index(): 16 print("welcom to index page") 17 @auth 18 def home(): 19 print("welcom to home page") 20 return "from home" 21 @auth 22 def bbs(): 23 print("welcom to bbs page") 24 25 26 index() 27 print(home()) 28 bbs()
终极版(添加判断)
1 username,password="alex","abc123" 2 def auth(auth_type): 3 def outer_wrapper(func): #就这么写吧,加一级。我也不知道为什么 4 def doc(*args,**kwargs): 5 if auth_type=="local": 6 user_input_username=input("请输入用户名:") 7 user_input_password=input("请输入密码:") 8 if user_input_username==username and user_input_password==password: 9 print("welcom back %s"%user_input_username) 10 return func(*args,**kwargs) #=运行下面的那个函数的返回值,so要return这个返回值到doc的函数。。实际上经过这一串操作。home()=doc() 11 #return func(*args,**kwargs) 12 else: 13 exit() 14 elif auth_type=="ldap": 15 print("ldap,我不会.00.00") 16 return doc 17 return outer_wrapper 18 19 def index(): 20 print("welcom to index page") 21 @auth(auth_type="local") 22 def home(): 23 print("welcom to home page") 24 #return "from home" 25 @auth(auth_type="ldap") 26 def bbs(): 27 print("welcom to bbs page") 28 29 30 index() 31 home() 32 bbs()
装饰器(易记忆版):
def inner(func): def doc(*args,**kwargs): 运行函数前要干的事 func(*args,**kwargs) # 执行函数 函数运行完之后要干的事 return doc @inner def func(a,b): pass
二、迭代器
迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退。另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁(Python在迭代过程中不能删除列表/字典中的元素)。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件
特点:
- 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
- 不能随机访问集合中的某个值 ,只能从头到尾依次访问
- 访问到一半时不能往回退
- 便于循环比较大的数据集合,节省内存
列表生成式:
g = [x * x for x in range(10)] #将列表生成式的[]改成()就好了 print(g) >> [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
迭代器:将列表生成式的[]改成()就好了
L = (x * x for x in range(10)) print(L) >> <generator object <genexpr> at 0x00000267957AD0F8> #保存的是一个算法
输出方式:
#一种输出值的方式:一直print(next(L)) print(next(L)) # 或print(L.__next__()) >> 0 1 4 9 16 25 36 49 64 81 #第二种输出方式 for i in L: print(i) >> 0 1 4 9 16 25 36 49 64 81
三、生成器:
一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator);如果函数中包含yield语法,那这个函数就会变成生成器;
def fib(max): # 斐波那契数列 n,a,b = 0,0,1 while n < max: yield b a,b = b,a+b n += 1 return 'done'
输出值的方法:
方法一:
data=fib(10) print(data.__next__()) #相当于print(next(data)) print(data.__next__()) print(data.__next__()) print(data.__next__()) print(data.__next__()) print(data.__next__()) print(data.__next__()) >> 1 1 2 3 5 8 13
方法二:
data=fib(10) for i in data: #Python的for循环本质上就是通过不断调用next()函数实现的 print(i) >> 1 1 2 3 5 8 13 21 34 55
Python的for循环本质上就是通过不断调用next()函数实现的
1 for x in [1, 2, 3, 4, 5]:
2
3 pass
4
5 完全等价于
6
7 # 首先获得Iterator对象:
8 it = iter([1, 2, 3, 4, 5])
9 # 循环:
10 while True:
11 try:
12 # 获得下一个值:
13 x = next(it)
14 except StopIteration:
15 # 遇到StopIteration就退出循环 没有return的返回值
16 break
方法三:(可以返回return的值)
1 def fib(max):
2 n,a,b = 0,0,1
3
4 while n < max:
5 #print(b)
6 yield b #保存函数的中断状态 并返回值
7 a,b = b,a+b
8
9 n += 1
10 return 'done'
11 g = fib(6)
12 while True:
13 try:
14 x = next(g) # g.__next__()
15 print('g:', x)
16 except StopIteration as e:
17 print('Generator return value:', e.value)
18 break
>> g: 1 g: 1 g: 2 g: 3 g: 5 g: 8 Generator return value: done