• 装饰器 迭代器


    装饰器

    有参装饰器的实现

    了解无参装饰器的实现原理后,我们可以再实现一个用来为被装饰对象添加认证功能的装饰器,实现的基本形式如下

    def deco(func):
        def wrapper(*args, **kwargs):
            #编写基于文件的认证,认证通过则执行res=func(*args, **kwargs),并返回res
    	return wrapper
    

    如果我们想提供多种不同的认证方式以供选择,单从wrapper函数的实现角度改写如下

    def deco(func):
        def wrapper(*args, **kwargs):
            if driver == 'file':
                print('基于文件认证通过')
                res = func(*args, **kwargs)
                return res
            elif driver == 'mysql':
                print('基于数据认证通过')
                res = func(*args, **kwargs)
                return res
            print('...')
    	return wrapper
    

    函数wrapper需要一个driver参数,而函数deco与wrapper的参数都有其特定的功能,不能用来接受其他类别的参数,可以在deco的外部再包一层函数auth,用来专门接受额外的参数,这样便保证了在auth函数内无论多少层都可以引用到

    def auth(driver):
        def deco(func):
            def wrapper(*args, **kwargs):
                if driver == 'file':
                    print('基于文件认证通过')
                    res = func(*args, **kwargs)
                    return res
                elif driver == 'mysql':
                    print('基于数据认证通过')
                    res = func(*args, **kwargs)
                    return res
            print('...')
            return wrapper
        return deco
    
    
    @auth(driver='aaa')#这里因为我们传入的参数没有
    #下面为该语法糖最后代表的内容
    #--->@和auth(driver='aaa')--->而auth(driver='aaa')相当于是调用函数auth得到结果为deco函数的内存地址,即此时这里为@deco,这里我们也可以将其分开为@和deco--->而@的作用就是相当于将被装饰对象的函数名当作参数传入该函数,所以现在就为deco(index),而该函数的结果为wrapper,所以这里我们可以写为wrapper=deco(index),即wrapper=wrapper  --->所以最后我们调用的函数其实是wrapper,但是装饰器的原则之一为不修改被装饰对象的调用方式,所以我们可以将wrapper函数对应的内存地址定义一个变量index=wrapper。
    def index():
        print('from index')
        
    index()
    #输出结果为
    ...
    

    可以使用help(函数名)来查看函数的文档注释,本质就是查看函数的__doc__属性,但对于被装饰之后的函数,查看文档注释

    import time
    def timer(func):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            res = func(*args, **kwargs)
            end_time = time.time()
            print('run time is %s'%(end_time - start_time))
            return res
        return wrapper
    
    @timer
    def home(name):
        '''
        home page function
        :param name:str
        :return:None
        '''
        time.sleep(5)
        print('Welcome to the home pae', name)
    print(help(home))
    #输出结果为
    Help on function wrapper in module __main__:
    
    wrapper(*args, **kwargs)
    
    None
    
    Process finished with exit code 0
    

    在被装饰之后home=wrapper,查看home.__name__也可以发现home的函数名确实是wrapper,想要保留原函数的文档和函数名属性,需要修正装饰器

    def timer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
            return res
        wrapper.__doc__=func.__doc__
        wrapper.__name__=func.__name__
        return wrapper
    

    按照上述方式来实现保留原函数属性过于麻烦,functools模块下提供一个装饰器wraps专门用来帮我们实现这件事,用法如下

    from functools import wraps
    
    def timer(func):
        @wraps(func)
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
            return res
        return wrapper
    

    迭代器

    迭代器
    迭代的工具。

        迭代:
            迭代指的是重复迭代,每一次迭代都是基于上一次的结果而来的。
    
        迭代器:
            迭代器指的是迭代取值的工具,它可以迭代取值。
    
        - 如果想要知道python中迭代器是什么?必须先知道什么是可迭代对象?
    
        - 可迭代对象:  所有的序列类型: str, list, tuple, dict, set, f
            凡是内部有str.__iter__()方法的都是可迭代对象。
    
        - 获取迭代器:
            通过可迭代对象.__iter__(), 得到的返回值就是 “迭代器对象”。
            迭代器是迭代取值的工具,作用是迭代取值。
    
        - 如何迭代取值:
            迭代器对象.__next__()  # “每一次执行”,都会从迭代器对象中取出一个值
    
    
        - 总结: 可迭代对象 VS 迭代器对象:
            - 获取可迭代对象: 定义序列类型(str, list, set, tuple, dict, f)
                - 特点:
                    内置有__iter__()
    
            - 获取迭代器对象: 通过可迭代对象调用.__iter__()得到返回值
                - 特点:
                    内置有__next__()
    
        - 迭代器对象的优点:
            - 优点:
                1.不依赖于索引迭代取值。
                2.节省内存空间。
    
            - 缺点:
                1.取指定某个值麻烦
                2.每次取值都要从第一个值开始,无法同过索引取值。
    
    
        for循环原理
            语法:     for i in 可迭代对象:
            in: 可迭代对象 ----> 内部会自动调用.__iter__() ---> 迭代器对象
            for line in list1:
                # 迭代器对象.__next__()
    
    
    
        - 迭代器本质上是一个可迭代对象
    
        - 文件本质上既是迭代器对象,也是可迭代对象。
    
        - 可迭代对象不一定是迭代器对象
  • 相关阅读:
    bzoj 1217: [HNOI2003]消防局的设立
    [USACO09FEB]庙会班车Fair Shuttle
    bzoj 1052: [HAOI2007]覆盖问题
    bzoj 1974: [Sdoi2010]代码拍卖会
    bzoj 1835: [ZJOI2010]基站选址
    bzoj 1875: [SDOI2009]HH去散步
    bzoj 3295: [Cqoi2011]动态逆序对
    bzoj 2120: 数颜色
    P1032 字串变换
    简析拓扑排序
  • 原文地址:https://www.cnblogs.com/a736659557/p/11892366.html
Copyright © 2020-2023  润新知