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()
posted @ 2017-04-11 17:53  hzxPeter  阅读(167)  评论(0编辑  收藏  举报