zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    【转】Eclipse插件开发之基础篇(1) 插件开发的基础知识
    js获取周.html
    Go语言 基础
    MySQL replace into
    元认知:思考“何为思考”
    redis 流水线
    关于Blog现象的一些思考。
    [LCS]LCS2005服务器应用程序
    [WAP]dotNet在WAP应用开发中实现按指定页数翻页的解决方案
    [Cache]深入学习Enterprise Library for .NET Framework 2.0的Cache机制——分析篇
  • 原文地址:https://www.cnblogs.com/x54256/p/7629337.html
Copyright © 2011-2022 走看看