python 函数装饰器

python 函数装饰器:

装饰器的作用就是在函数调用方法不变的情况下,把一个函数封装到另一个函数里面,执行这个函数时自己去调用另一个函数.

装饰器本质也是函数,(装饰其他函数)就是为其他函数添加附加功能.

一、了解装饰器之前,先看看下面这个列子.

#!/usr/bin/env python
#coding:utf-8

def deco(arg):      # arg=func
    arg()           # arg() = func()

def func():
    print("Hello func ")

deco(func)

-------------------------------------------------------------------
#执行顺序
1.执行def deco(arg): 将其加载进内存.内容不执行
2.执行def func():将其加载进内存.内容不执行
3.执行deco(func) 给deco传的参数为func,这个参数为func()函数的函数名
4.执行def deco(arg):    ===> arg = func ===> arg() ==func()
5.执行arg()即func()函数      ==>  func()
6.打印出func()执行结果,即print("Hello func ")

总结:把一个函数func()封装到另一个函数deco(arg)里面,执行这个函数deco(func)时自己去调用另一个函数.

 二、看看带 return 的函数

#!/usr/bin/env python
#coding:utf-8

# 替换函数(装饰)
# 装饰函数的参数是被装饰的函数对象,返回原函数对象
# 装饰的实质语句: test = deco(test)

def deco(func):     #func = test ==> func()=test()
    print("before")
    func()
    print("after")
    return func     #return test函数内存地址

def test():
    print("My test func")

test = deco(test)     # 重新定义了一个变量名test,指向deco(func),这样可以不用改变调用函数的名称.
test()                # 调用函数.

----------------------------------------------------
before
My test func
after
My test func

上面的调用方式可以写成如下,执行结果一样.

#!/usr/bin/env python
#coding:utf-8

def deco(func):     #func = test ==> func()=test()
    print("before")
    func()
    print("after")
    return func     #return test函数内存地址
@deco    # test=deco(test) 等价于 @deco,学名为装饰器的语法糖
def test():
    print("My test func")
    
test()                # 调用函数.

-----------------------------------------------------
before
My test func
after
My test func

 使用双层装饰函数来给函数附加额外功能:

#!/usr/bin/env python
#coding:utf-8

import time

def timer(func):         # func=test ==> timer(test):
    def deco():
        start_time = time.time()
        func()      #运行 test()函数
        stop_time = time.time()
        print("run time %s" %(stop_time-start_time))
    return deco     #deco代表返回函数名,非执行函数,

@timer          # test=timer(test)
def test():
    time.sleep(2)
    print("Hello test1")
test()      #调用函数,在调用函数名不变的情况下,先执行装饰函数中的deco()块,在执行test()函数.

------------------------------------------------------------
Hello test1
run time 2.0001144409179688

#总结:
@timer  <==> test=timer(test)这句,是简化的写法.使用语法糖@来装饰函数

@timer 等于函数执行了两次:
          1.执行timer函数,把被装饰的函数作为参数timer(test)
          2.将timer函数的返回值,赋值给被装饰的函数的函数名.

 那么问题来了,被装饰的函数如果有参数呢,如下我要装饰test1和test2函数,test1没有参数,而test2有参数,这时候就用到了装饰器动态参数,

#!/usr/bin/env python
#coding:utf-8

import time

def timer(func):         # func=test ==> timer(test):
    def deco(*args,**kwargs):
        start_time = time.time()
        func(*args,**kwargs)      #运行 test()函数
        stop_time = time.time()
        print("run time %s" %(stop_time-start_time))
    return deco     #deco代表返回函数名,非执行函数,

@timer          # test=timer(test)
def test1():
    time.sleep(2)
    print("Hello test1")

@timer
def test2(name, age):
    print("Hello test2:", name, age)


test1()         #调用函数,在调用函数名不变的情况下,先执行装饰函数中的deco()块,在执行test()函数.
test2("saneri",33)

---------------------------------------------------------------
Hello test1
run time 2.0001144409179688
Hello test2: saneri 33
run time 0.0

下面我们来看一个简单的完整的用户登录认证的装饰器函数:

#!/usr/bin/env python
#coding:utf-8

"""
知识点:
1.模拟网站登陆认证,home和bbs页面需要登陆才可以访问.
2.home 认证后有return返回值

"""
user,passwd = "saneri","123"
def auth(func):  # func <==> home
    def wrapper(*args,**kwargs):
        username = input("Username:").strip()
        password = input("Password:").strip()
        if user == username and passwd == password:
            print("\033[31;1m请输入用户名和密码认证\033[0m")
            return func(*args,**kwargs)  # <==> home(*args,**kwargs)
        else:
            exit("\033[31;1m认证失败,用户名或密码错误!\033[0m")
    return wrapper

def index():
    print("Welcom to index page !")
@auth  # home = auth(home)
def home():
    print("Welcom to home page !")
    images_list = ['views','images','template','video']
    return images_list
@auth   #bbs = auth(bbs)
def bbs():
    print("Welcom to bbs page !")

index()
ret = home()
print(ret)
bbs()

 

参考链接:https://www.cnblogs.com/saneri/p/4992586.html

 

posted @ 2018-12-08 22:58  梦徒  阅读(261)  评论(0)    收藏  举报