04-python 学习第四点-装饰器

装饰器就是一个函数,他是通过不修改某个函数的源代码和调用方式的前提下可以添加新功能的一种函数。在python 中装饰器一般采用高阶函数和嵌套函数达到装饰的作用,下面进行实例讲解:

1、目前有一个网址有很多页面(比如:index,home,bbs)。因为时老文字,所有页面都是可以直接浏览的。实现效果如下:

def home():#模拟网页homne
    print("wolcome to home")


def bbs():#模拟网页bbs
    print("wolcome to bbs")


index() #调用index
home()  #调用home
bbs()   #调用bbs

  运行结果如下:各个网站均可以直接浏览

wolcome to index
wolcome to home
wolcome to bbs

2、公司有了新规定要求主页indezx 保留原始状态直接浏览,home 和bbs 需要登录才能浏览,不允许修改目前的函数源代码和调用方式实现这个功能。这下则么办呢?

我们可以为需要登录才能浏览的网页home 和bbs 函数进行装饰即可。

user, passwd = 'dwdar', 'abc123'  # 模拟用户名密码数据库


def auth(func):  # 登录装饰器
    def wrapper():
        username = input("UserName:").strip()
        password = input("Password:").strip()
        if user == username and passwd == password:
            print("登录成功")
            func()
        else:
            exit("验证失败!")

    return wrapper


def index():
    print("wolcome to index")


@auth  # home 被装饰(没有修改源代码和调用方式)
def home():
    print("wolcome to home")


@auth  # bbs被装饰(没有修改源代码和调用方式)
def bbs():
    print("wolcome to bbs")


index()
bbs()
home()

  运行结果:

index 直接可以显示

wolcome to index

随后要求输入用户名和密码,登录后才能浏览home 和bbs

UserName:dwdar
Password:abc123
登录成功
wolcome to bbs
UserName:dwdar
Password:abc123
登录成功
wolcome to home

3、通过几年的发展,网站又有了新的要求,home 这个函数需要返回值了,需要我们更新以下装饰器。

假设home的返回值是这样的。

@auth  # home 被装饰(没有修改源代码和调用方式)
def home():
    print("wolcome to home")
    return "from home"  #home 需要返回值

  目前的装饰器是无法实现返回值的,我们对装饰器进行如下升级即可打印返回值了。

 1 # Author:Dwdar
 2 
 3 user, passwd = 'dwdar', 'abc123'  # 模拟用户名密码数据库
 4 
 5 
 6 def auth(func):  # 登录装饰器
 7     def wrapper(*args,**kwargs):
 8         username = input("UserName:").strip()
 9         password = input("Password:").strip()
10         if user == username and passwd == password:
11             print("登录成功")
12             res = func(*args,**kwargs)
13             return res
14         else:
15             exit("验证失败!")
16 
17     return wrapper
18 
19 
20 def index():
21     print("wolcome to index")
22 
23 
24 @auth  # home 被装饰(没有修改源代码和调用方式)
25 def home():
26     print("wolcome to home")
27     return "from home"  # home 需要返回值
28 
29 
30 @auth  # bbs被装饰(没有修改源代码和调用方式)
31 def bbs():
32     print("wolcome to bbs")
33 
34 
35 index()
36 bbs()
37 print(home())       #打印home的返回值

 4、又过了一段时间,网站又有了新变化,要求BB 用本地认证系统登录,而BBS需要ldap 认证服务器登录。这下怎么办呢?

第一步:首选我们想到调用装饰器需要传参,通过装饰器参数来判断调用方式。调用装饰器如下。

def index():
    print("wolcome to index")


@auth(auth_type="local")  # 装饰器需要传参,通过参数判断登录方式
def home():
    print("wolcome to home")
    return "from home"


@auth(auth_type="ldap")  # 装饰器需要传参,通过参数判断登录方式
def bbs():
    print("wolcome to bbs")

第二步:装饰器再添加一层函数 outer_wrappr 来接收相关参数最终可以实现判断。

完整代码如下:

# Author:Dwdar
'''
有一个网址有多个页面,大部分页面时直接浏览的。比如index
后来有了新的要求:
要对home 和页面BBS页面登录才能预览。通过装饰器需要给home 和BBS 添加登录的功能怎么做呢?



'''

user, passwd = 'dwdar', 'abc123'
bbsuser, bbspasswd = 'bbs', 'bbs123'  # 模拟ldap 认证账号


def auth(auth_type):
    # print("auth func:", auth_type)

    def outer_wrappr(func):
        def wrapper(*args, **kwargs):
            # print("wrapper func arges:", *args, **kwargs)
            if auth_type == "local":
                username = input("UserName:").strip()
                password = input("Password:").strip()
                if user == username and passwd == password:
                    print("登录成功")
                    res = func(*args, **kwargs)
                    return res
                else:
                    exit("验证失败!")
            elif auth_type == "ldap":
                username = input("bbsUserName:").strip()
                password = input("bbsPassword:").strip()
                if bbsuser == username and bbspasswd == password:
                    print("登录成功")
                    res = func(*args, **kwargs)
                    return res
                else:
                    exit("BBS验证失败!")

        return wrapper

    return outer_wrappr


def index():
    print("wolcome to index")


@auth(auth_type="local")  # 装饰器需要传参,通过参数判断登录方式
def home():
    print("wolcome to home")
    return "from home"


@auth(auth_type="ldap")  # 装饰器需要传参,通过参数判断登录方式
def bbs():
    print("wolcome to bbs")


index()
bbs()
print(home())

运行结果:

wolcome to index
bbsUserName:bbs
bbsPassword:bbs123
登录成功
wolcome to bbs
UserName:

通过判断登录BBS需要输入用户名:BBS的账号和密码才能进入。

猜你喜欢

转载自www.cnblogs.com/dwdar/p/11691256.html