1、装饰器

1.1、装饰器定义

装饰器:
定义:本质上是函数,(装饰器的功能:装饰其他函数),就是为其他函数添加附加的功能。

原则:
1.不能修改被装饰的函数的源代码
2.不能修改被装饰的函数的调用方式

简单装饰器程序演示:计算test1函数的运行时间
import time
def timemer(func):  #使用高阶函数定义装饰器
    def warpper(*args,**kwargs): #装饰器的函数,函数体为装饰器的功能主体
        start_time=time.time()
        func()  #run test1在装饰器的功能主体中调用原函数,实现原函数的功能
        stop_time=time.time()
        print('the func run time is %s' %(stop_time-start_time))
    return warpper #返回了warpper的内存地址信息,下次再调用时加上()才会执行warpper函数
@timemer #调用装饰器
def test1():
    time.sleep(3)
    print("in the test1")

test1() #执行主函数

执行结果:
in the test1
the func run time is 3.000171661376953

小结:这里增加了计算函数运行时间的功能,并且不修改原函数的代码,又不影响原来函数的调用方式。

实现装饰器知识储备:
1.函数即"变量"
2.高阶函数
a: 把一个函数名当做实参传给另外一个函数(在不修改被装饰函数源代码的情况下为其添加功能)
b: 返回值中包含函数名(不修改函数的调用方式)

3.嵌套函数
高阶函数+嵌套函数==>装饰器

1.2、装饰器传参

import time

def timer(func):---->使用高阶函数定义装饰器
    def deco(*args,**kwargs):  #为了解决装饰器的通用性,结合非固定参数解决不同函数需要传参的问题
        start_time=time.time()
        func(*args,**kwargs)
        stop_time=time.time()
        print("the func run time is %s" %(stop_time-start_time))
    return deco #此处返回的值是deco的内存地址

@timer #test1=timer(test1),相当于获取了deco的内存地址
def test1():
    time.sleep(1)
    print("in the test1")

@timer #test2=timer(test2),相当于获取了deco的内存地址
def test2(name,age):
    time.sleep(1)
    print("in the test2",name,age)

#test1=timer(test1)
test1()
test2("kim",19)

执行结果:
in the test1
the func run time is 1.0000572204589844
in the test2 kim 19
the func run time is 1.0000572204589844

1.3、程序练习

需求:网站多页面,一个页面代表一个函数,网站谁都可以登录。现在需要在一些页面中增加验证功能登录
#!/usr/bin/python
# _*_ coding:utf-8 _*_
# Aothr: Kim
user, passwd = 'alex', '123'
def auth(auth_type):
    def out_wrapper(func):
        def wrapper(*args,**kwargs):
            if auth_type == "local":
                print("Authing for file")
                username = input("Login:").strip()
                password = input("Password:").strip()
                if username == user and password == passwd:
                    print("You has passed the authentication.")
                    func(*args,**kwargs)
                else:
                    exit("Your username or password is invalid.")
            elif auth_type == "ldap":
                print("Authing for LDAP.")
                print("You has passed the ldap authentication.")
                func(*args, **kwargs)
        return wrapper
    return out_wrapper

def index():
    print("welcome to index page")

@auth(auth_type="local")
def home():
    print("welcome to home page")

@auth(auth_type="ldap")
def bbs():
    print("welcome to bbs page")

#index()
Page_list = ["index","home","bbs"]
for i in Page_list:
    print(i)

choice = input("Please enter the page you want to view:").strip()
if choice == "index":
    index()
elif choice == "home":
    home()
elif choice == "bbs":
    bbs()
else:
    exit("The page you selected does not exist.")