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的文件

特点:

  1. 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
  2. 不能随机访问集合中的某个值 ,只能从头到尾依次访问
  3. 访问到一半时不能往回退
  4. 便于循环比较大的数据集合,节省内存

列表生成式:

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

原文地址:https://www.cnblogs.com/x54256/p/7629337.html