• Python装饰器


    关于开放封闭原则,其核心的思想是:
    软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。
    因此,开放封闭原则主要体现在两个方面:
    对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。
    对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改。
    “需求总是变化”、“世界上没有一个软件是不变的”,这些言论是对软件需求最经典的表白。从中透射出一个关键的意思就是,对于软件设计者来说,必须在不需要对原有的系统进行修改的情况下,实现灵活的系统扩展。

    不修改源代码、不修改调用方式,上线后还需要扩展,就用到了装饰器
    装饰器可以是任何可调用对象

    1 装饰器

    1.1 无参装饰器,为被装饰的函数添加统计时间功能

    装饰器用到的是闭包函数,在下面的例子中是wrapper函数,我们首先需要了解程序的运行流程,下面一步步的分析:

    程序运行到@timmer时,会执行timmer(index) ,index是timmer下面最近的函数名,函数名index作为timmer的参数,下面运行timmer函数。timmer函数运行结束会返回wrapper,继续运行到@timmer,timmer(index)的返回值会赋值给index,也就是index=timmer(index) 。然后执行最后的index()函数,此时实际是wrapper(),然后进入到wrapper函数中执行,wrapper函数是闭包函数,内部有个func函数,执行到这里的时候,wrapper函数颞部没有定义func,就到其外部作用域寻找,在这里是timmer函数传入的参数func。wrapper中的func的地址是最初的index函数的地址,所以执行就是执行下面的index中的 time.sleep(1) print("welcome index page")着两句。

    #-*- coding:utf-8 -*-
    # decription:定义无参装饰器,为被装饰的函数添加统计时间功能
    # author: hzx
    # date: 2017.04.10
    
    import time
    def timmer(func):
        def wrapper():   # wrapper 是闭包函数
            time_start= time.time()
            res=func()   # 这里是最初的index
            time_stop = time.time()
            print("run time is %s"%(time_stop-time_start))
            return res
        return wrapper
    
    
    @timmer
    def index():  # index=timmer(index)
        time.sleep(1)  # 延时函数2秒
        print("welcome index page")
    index()  # 相当于是wrapper()
    

    1.2 有参装饰器,为被装饰函数添加函数认证功能

    有参装饰器是在无参装饰器的的外面再添加一个函数,这个函数负责接收的参数是用于判读用户信息的来源,这里测试是从文件中读取用户信息。

    程序思路:
    首先程序执行道@auth_file(auth_type="file"),这是auth外面的函数,它的返回值是auth,重点-->,此时程序就是@auth,思路和无参装饰器是一样的,index=auth(index).

    程序分为3部分,装饰器定义部分,被装饰函数,函数引用。

    #-*- coding:utf-8 -*-
    # decription:定义有参装饰器,为被装饰的函数添加函数认证功能,
    #            用户信息可以来源文件或者ldap三次登录失败,锁定用户
    # author: hzx
    # date: 2017.04.10
    
    import os
    
    current_login = {"name":None,"login":False}  # 定义的是用户的登录状态
    def auth_file(auth_type):  # 定义有参装饰器函数
        def auth(func):
            def wrapper(*args,**kwargs):  # 这样就能接收任何数据类型 数据来自func
                if current_login["name"]  and current_login["login"]: # 在用户认证之情判断
                    res  =func(*args,**kwargs)  # 如果认证功过,就直接返回res
                    return res
                if auth_type == "file":
                    username = input("please input username:")
                    # user_func()
                    count = 0  # 记录用户输入密码的次数
                    flag = 1
                    lock = []
                    user_pass = []
                    with open("locked", encoding="utf-8") as locked_file:
                        for i in locked_file:
                            if i == username:
                                print("用户名被锁定")
                                break
                                # 将黑名单文件内容作为列表元素追加到列表中
                        for line in locked_file:
                            line = line.strip()
                            lock.append(line)
                    # 若输入的用户名在黑名单中,打印:用户已经被锁定,
                    if username in lock:
                        print("用户%s" % username)
                    else:
                        # 输入的用户名不在黑名单中,则提示用户输入密码信息
                        while True:
                            count += 1
                            passwd = input("please input your password:")
                            with open("user", encoding="utf-8") as user_file:
                                for i in user_file:
                                    user_pass = i.strip().split("--")
                                    print(user_pass)
                                    if username == user_pass[0] and passwd == user_pass[1]:
                                        print('welcome user %s login !' % username)
                                        print("认证成功!")
                                        res = func(*args, **kwargs)  # 这样设置然函数也能接收任何类型的数据,
    					 current_login["name"] = username
                                        current_login["login"] = True
                                        return res
    
                                        # flag = True
                                        break
                                    else:
                                        continue
                                if flag is True:
                                    break
                                else:
                                    if count == 3:
                                        print('Locked')
                                        with open("locked", "w+", encoding="utf-8") as f_write:
                                            f_write.write(username)  # 3次输入错误后将用户名写入locked文件
                                        break
                elif auth_type == "ldap":
                    print("等待使用")
            return wrapper
        return auth
    
    @auth_file(auth_type="file")
    def index():
        print("welcome to index page!")
    
    @auth_file(auth_type="ldap")
    def home():
        print("welcome to home page!")
    
    # 函数调用
    index()
    home()
    
  • 相关阅读:
    绿色通道
    Banknotes
    旅行问题
    修剪草坪
    最大连续和
    动物园
    炮兵阵地
    涂抹果酱
    牧场的安排
    国王
  • 原文地址:https://www.cnblogs.com/Python666/p/6694679.html
Copyright © 2020-2023  润新知