zoukankan      html  css  js  c++  java
  • day047函数之装饰器(闭包的运用),面向对象之单例模式(设计模式)

    本节内容:

    1、函数之装饰器
    2、面向对象之单例模式
    

    一、函数之装饰器(闭包的运用)

    装饰器本质上就是一个python函数,一个闭包函数的运用,
    他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。
    
    装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。
    

    1、装饰器的形成过程

    现在有一个需求,要测试一个函数的执行时间,在不改变这个函数的执行情况下:
    

    fe1:简单版的装饰器

    简单版的装饰器

    # 增加一个函数 测试其他函数执行效率的功能,但是尽量不要改变原函数的执行方式.
    
    import time
    
    def func():  # 被装饰的函数
        time.sleep(0.2)
        print('10万行代码')
    
    def func1():
        time.sleep(0.2)
        print('11万行代码')
    # func = 666
    # func()
    
    def timmer(f):  # func函数名 = f
        def inner():
            start_time = time.time()
            f()
            end_time = time.time()
            print('此函数的执行效率为%s' % (end_time - start_time))
        return inner
    
    func = timmer(func)  # inner
    func()  # inner()
    func1 = timmer(func1)
    func1()
    
    # 上个版本不行,每次执行被测试时间的函数时,必须要加一行代码.
    # 怎么解决,看下面的语法糖
    
    Python

    fe2:装饰器—-语法糖

     装饰器:在不改变原函数的执行(代码机构基础上,给原函数增加一些额外的功能,登录验证,打印日志,测试效率等等.
     语法糖,就是python里面封装好的func = timmer(func),你直接调用就行,不用再自己写了
    

    装饰器的语法糖运用

    import time
    def timmer(f):  # func函数名 = f
        def inner(x,y):
            start_time = time.time()
            f(x,y)
            end_time = time.time()
            print('此函数的执行效率为%s' % (end_time - start_time))
    
        return inner
    
    @timmer #  func = timmer(func)
    def func(x,y):
        time.sleep(0.2)
        print(x + y)
    
    # 语法糖  @
    # @timmer  # func1 = timmer(func1)
    # def func1():
    #     print(666)
    func(10,20)  # inner(10,20)
    # func1()
    
    Python

    fe3:被装饰函数带参数,这时用无敌传参(*args, **kwargs)

    无敌传参解决被装饰函数带参数

    import time
    def timmer(f):  # func函数名 = f
        def inner(*args, **kwargs):  # 传参,聚合
            # args = (10,20)
            start_time = time.time()
            f(*args,**kwargs)  # 被装饰函数的执行  * 打散 10 , 20  f(10,20)
            end_time = time.time()
            print('此函数的执行效率为%s' % (end_time - start_time))
        return inner
    
    @timmer #  func = timmer(func)  func2 = timmer(func2) 这时的func2已经不是被装饰函数了
    def func(x,y):
        time.sleep(0.2)
        print(x + y)
    
    @timmer
    def func2(x,y,z,w):
        print(x,y,z,w)
    # func(10, 20)  # inner(10,20)
    
    func2(1,2,3,w=4)  # 这里的参数被inner的f接收了,f就是语法糖传参的被装饰函数名
    
    Python

    fe4: 标准的装饰器, 被装饰的函数带参数,带返回值

    标准的装饰器

    import time
    def timmer(f):  # func函数名 = f
        def inner(*args, **kwargs):   # 接收被装饰函数的参数
            start_time = time.time()
            ret = f(*args,**kwargs)  # 接收被装饰函数执行之后的返回值
            end_time = time.time()
            print('此函数的执行效率为%s' % (end_time - start_time))
            return ret  # 将返回值,返回给调用者
        return inner
    
    @timmer #  func = timmer(func)
    def func(x,y,z,e):
        time.sleep(0.2)
        return x + y + z + e
    ret1 = func(10, 30, 3, 4)  # inner(10, 30)
    print(ret1)
    
    Python

    2、面试题(手写一个装饰器)

    def wrapper(f):
        def inner(*args, **kwargs):
            '''被装饰函数执行之前的操作'''
            ret = f(*args, **kwargs)
            """被装饰函数执行之后的操作"""
            return ret
        return inner
    
    Python

    3、装饰器的应用: 登录验证.

    需求:登陆后可以在各个页面切换
    

    名字

    dic_status = {
        'username': None,
        'status': False,
    }
    
    def login(f):
        def inner(*args, **kwargs):
            '''被装饰函数执行之前的操作'''
            if dic_status['status'] :
                ret = f(*args, **kwargs)
                return ret
            else:
                username = input('请输入用户名').strip()
                password = input('请输入密码').strip()
                with open('register', encoding='utf-8') as f1:
                    for line in f1:
                        user, pwd = line.split('|')
                        if username == user.strip() and password == pwd.strip():
                            dic_status['username'] = username
                            dic_status['status'] = True
                            print('登录成功,正在跳转...')
                            ret = f(*args, **kwargs)
                            return ret
                    else:
                        print('登录失败...')
        return inner
    
    
    @login
    def article():
        print('欢迎登录文章页面')
    @login
    def diary():
        print('欢迎登录日记页面')
    @login
    def comment():
        print('欢迎登录评论页面')
    
    dic = {
        1: article,
        2: diary,
        3: comment,
    }
    
    while 1:
        num = input('欢迎访问博客园,请选择:
    1文章页面 
    2 日记页面 
     3 评论页面').strip()
        if num.isdigit():
            dic[int(num)]()
        else:
            print('重新输入..')
    # 还需写一个register的文件来放用户信息,进行登录验证
    
    Python

    4、带参数的装饰器

    带参数的装饰器

    import time
    def timmer(flag):  # 这个函数的作用是,将参数传给装饰器函数
        def wrapper(f):  # 这个函数的作用是:将被装饰函数作为参数传入
            def inner(*args, **kwargs):  # 传入被装饰函数的参数,传参
                if flag:  # 通过这个状态来,控制是否执行装饰器函数
                    start_time = time.time()
                    ret = f(*args, **kwargs)
                    end_time = time.time()
                    print('执行时间%s' % (end_time-start_time))
                    return ret
                else:
                    ret = f(*args, **kwargs)
                    return ret
            return inner
        return wrapper
    
    flag1 = False
    @timmer(flag1)  # 第一步,将@ 与后面 分开,只是单纯的执行timmer(flag1)函数 第二部 将@ 与 wrapper相结合,形成装饰器
    def func1():
        time.sleep(0.3)
        print('in func1')
    func1()
    
    Python

    5、多个装饰器 装饰一个函数

    多个装饰器 装饰一个函数

    def wrapper1(func):  # func == f 函数名
        def inner1():
            print('wrapper1 ,before func')  # 2
            func()
            print('wrapper1 ,after func')  # 4
        return inner1
    
    def wrapper2(func):  # func == inner1
        def inner2():
            print('wrapper2 ,before func')  # 1
            func()
            print('wrapper2 ,after func')  # 5
        return inner2
    
    # 就近原则   先将近的传给装饰器函数,多个装饰器的话,逐层上传
    @wrapper2  # f = wrapper2(f) 里面f == inner1  外面的f == inner2
    @wrapper1  # f = wrapper1(f) 里面的f == 函数名f   外面的f == inner1
    def f():
        print('in f')  # 3
    f()  # inner2()
    
    Python

    二、面向对象之单例模式

    就是只能实例化一个对象,不管创建多少个对象,都是指向同一个内存地址
    
    例如:多个py文件在引入同一个模块,如果没有设置
    

    1、单例模式代码示例

    class A:
        __instance = None   # 定义一个私有变量,
        def __new__(cls, *args, **kwargs):  # 通过重写父类的__new__方法,来控制指向第一个实例化对象的地址
            if A.__instance is None:     # 通过私有变量来控制指向第一个实例化对象的(同一个)的地址
                obj = object.__new__(cls)  # 如果是第一次实例化对象,就创建对象,
                A.__instance = obj
            return A.__instance   # 如果不是第一次,就直接指向第一次对象的内存地址,不再创建对象
    
    obj1 = A()
    obj2 = A()
    obj3 = A()
    obj4 = A()
    print(obj1)  # 都指向同一个内存地址
    print(obj2)
    print(obj3)
    print(obj4)
  • 相关阅读:
    ClickOnce發布經驗
    reporting Server組件不全引起的致命錯誤
    異步調用
    Usercontrol Hosted in IE
    MATLAB命令大全(转载)
    一种保护眼睛的好方法
    关于oracle自动编号
    An Algorithm Summary of Programming Collective Intelligence (1)
    An Algorithm Summary of Programming Collective Intelligence (3)
    An Algorithm Summary of Programming Collective Intelligence (4)
  • 原文地址:https://www.cnblogs.com/yipianshuying/p/10153645.html
Copyright © 2011-2022 走看看