Python装饰器

Posted zhangzixiang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python装饰器相关的知识,希望对你有一定的参考价值。

一.相关定义

补:__iter__()  ==  iter()

装饰器:本质就是函数,为其它函数添加附加功能

原则:

1. 不修改被修饰函数的源代码

2. 不修改被修饰函数的接口(即调用方式)

装饰器的知识储备

装饰器 = 高阶函数 + 函数嵌套 + 函数闭包

def cal(l):
    start_time = time.time()
    res = 0
    for i in l:
        time.sleep(0.1)
        res+=i
    stop_time = time.time()
    print(函数的运行时间是%s %(stop_time-start_time))
    return res

print(cal(range(10)))

result:
函数的运行时间是1.0016779899597168
45
import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)
        stop_time = time.time()
        print(函数运行的时间是%s %(stop_time-start_time))
        return res
    return wrapper


@timmer
def cal(l):
    res = 0
    for i in l:
        time.sleep(0.1)
        res+=i
    return res

print(cal(range(10)))

result:
函数运行的时间是1.0017824172973633
45

二.高阶函数

1. 函数接收的参数是函数名

2. 函数返回值是一个函数名

3. 满足上述任意一条的都是高阶函数

 

接收的值是函数名

import time
def foo():
    time.sleep(3)
    print(hello)

def test(func):
    #print(func)
    start_time = time.time()
    func()
    stop_time = time.time()
    print(函数运行时间是 %s %(stop_time - start_time))

test(foo)  #违反了装饰器的原则,调用方式改变了

resut:
hello
函数运行时间是 3.0026164054870605

调用方式不改变

def foo():
    print(from the foo)

def test(func):
    return func

# res = test(foo)
#
# res()

foo = test(foo)
foo()

result:
from the foo

不修改源代码,不修改调用方式

import time
def foo():
    time.sleep(3)
    print(from the foo)

def timer(func):
    #print(func)
    start_time = time.time()
    func()
    stop_time = time.time()
    print(函数运行时间是 %s %(stop_time - start_time))
    return func

foo = timer(foo)
foo()

result:
from the foo
函数运行时间是 3.001885414123535
from the foo

多运行了一次! 高阶函数实现不了装饰器的功能

三.函数嵌套

#函数嵌套
def father(name):
    print(from father %s %name)
    def son():
        print(from the son)
    print(locals())

father(Joey)

result:
from father Joey
{son: <function father.<locals>.son at 0x7f4acb23d620>, name: Joey}

函数嵌套 -->> 函数闭包

四.函数闭包

#装饰器的框架
import time
def timer(func):
    def wrapper():
        start_time = time.time()
        func()         #就是下运行test
        stop_time = time.time()
        print(运行时间是%s %(stop_time-start_time))
    return wrapper

def test():
    time.sleep(1)
    print(test函数运行完毕)

test = timer(test)  #返回wrapper的地址
test()     #执行wrapper函数

result:
test函数运行完毕
运行时间是1.0012073516845703
@timer == test=timer(test)
#装饰器的框架
import time

def timer(func):
    def wrapper():
        start_time = time.time()
        func()         #就是下运行test
        stop_time = time.time()
        print(运行时间是%s %(stop_time-start_time))
    return wrapper
@timer   #写在timer()后面
def test():
    time.sleep(1)
    print(test函数运行完毕)

#test = timer(test)  #返回wrapper的地址
test()     #执行wrapper函数

进一步改进,加上返回值

#装饰器的框架
import time
def timer(func):
    def wrapper():
        start_time = time.time()
        res = func()         #就是下运行test
        stop_time = time.time()
        print(运行时间是%s %(stop_time-start_time))
        return res
    return wrapper
@timer
def test():
    time.sleep(1)
    print(test函数运行完毕)
    return 这是test的返回值

res = test()  #返回wrapper的地址
print(res)

result:
test函数运行完毕
运行时间是1.0005300045013428
这是test的返回值

函数闭包加上参数

#装饰器的框架
import time
def timer(func):
    def wrapper(name,age,gender):
        start_time = time.time()
        res = func(name,age,gender)         #就是下运行test
        stop_time = time.time()
        print(运行时间是%s %(stop_time-start_time))
        return res
    return wrapper
@timer
def test(name,age,gender):
    time.sleep(1)
    print(test函数运行完毕  姓名:%s ;性别:%s ; 年龄:%d %(name,gender,age))
    return 这是test的返回值

res = test(alex,18,male)  #返回wrapper的地址
print(res)

result:
test函数运行完毕  姓名:alex ;性别:male ; 年龄:18
运行时间是1.001114845275879
这是test的返回值

进一步优化,使之能够接收任意长度的参数

#装饰器的框架
import time
def timer(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)         #就是下运行test
        stop_time = time.time()
        print(运行时间是%s %(stop_time-start_time))
        return res
    return wrapper
@timer
def test(name,age,gender):
    time.sleep(1)
    print(test函数运行完毕  姓名:%s ;性别:%s ; 年龄:%d %(name,gender,age))
    return 这是test的返回值

res = test(alex,age=18,gender=male)  #返回wrapper的地址
print(res)

result:
test函数运行完毕  姓名:alex ;性别:male ; 年龄:18
运行时间是1.0011067390441895
这是test的返回值
def test2(name,age,gender):
    print(name)
    print(age)
    print(gender)

def test1(*args,**kwargs):
    test2(*args,**kwargs)


test2(alex,18,gender=male)
test1(Joey,18,male)

#解压序列
a,b,c = (1,2,3)
print(a,b,c)

result:
alex
18
male
Joey
18
male
1 2 3

补: 解压序列

l = (1,2,3,4,5,6,7,8,9,0)
# a,b,c = ‘hello‘
# print(a,b,c)  # 必须一一对应

a,b,c = hel
print(a,b,c)

a,*_,c = l
print(a=%d %a)
print(c=%d %c)
a,*b,c = l
print(b=%s %b)

m=1
n=2
m,n=n,m
print(m=%d,n=%d %(m,n))

result:
h e l
a=1
c=0
b=[2, 3, 4, 5, 6, 7, 8, 9]
m=2,n=1

五.功能实现

认证功能装饰器

def auth_func(func):
    def wrapper(*args,**kmargs):
        username=input(用户名:).strip()
        passwd=input(密码:).strip()
        if username == alex and passwd == 123:
            res = func(*args,**kmargs)
        else:
            print(用户名或密码错误)
        return res
    return wrapper
@auth_func
def index():
    print(欢迎来到京东主页)
    pass
@auth_func
def home():
    print(欢迎回家)
    pass
@auth_func
def cart():
    print(购物车里有[%s,%s,%s] %(零食,书籍,衣服))
    pass
@auth_func
def order():
    pass

index()
home()
cart()
order()

result:
用户名:alex
密码:123
欢迎来到京东主页

功能改进: 只登录一次(记录登录状态)

user_dic = {username:None,login:False}
def auth_func(func):
    def wrapper(*args,**kmargs):
        if user_dic[username] and user_dic[login]:
            res = func(*args, **kmargs)
            return res
        username=input(用户名:).strip()
        passwd=input(密码:).strip()
        if username == alex and passwd == 123:
            user_dic[username] = alex
            user_dic[login] = 123
            res = func(*args,**kmargs)
        else:
            print(用户名或密码错误)
        return res
    return wrapper
@auth_func
def index():
    print(欢迎来到京东主页)
    pass
@auth_func
def home():
    print(欢迎回家)
    pass
@auth_func
def cart():
    print(购物车里有[%s,%s,%s] %(零食,书籍,衣服))
    pass
@auth_func
def order():
    pass

index()
home()
cart()
order()

result:
用户名:alex
密码:123
欢迎来到京东主页
欢迎回家
购物车里有[零食,书籍,衣服]

功能改进,添加用户名密码存储列表

user_list = [
    {name:alex,passwd:123},
    {name:Joey,passwd:234},
    {name:Tony,passwd:345},
]
current_dic = {username:None,login:False}
def auth_func(func):
    def wrapper(*args,**kmargs):
        if current_dic[username] and current_dic[login]:
            res = func(*args, **kmargs)
            return res
        username=input(用户名:).strip()
        passwd=input(密码:).strip()
        for user_dic in user_list:
            if username == user_dic[name] and passwd == user_dic[passwd]:
                current_dic[username] = username
                current_dic[login] = passwd
                res = func(*args, **kmargs)
                return res
        else:
            print(用户名或密码错误)
    return wrapper
@auth_func
def index():
    print(欢迎来到京东主页)
    pass
@auth_func
def home(name):
    print(欢迎回家%s %name)
    pass
@auth_func
def cart():
    print(购物车里有[%s,%s,%s] %(零食,书籍,衣服))
    pass
@auth_func
def order():
    pass
index()
print(current_dic)
home(alex)

result:
用户名:alex
密码:123
欢迎来到京东主页
{username: alex, login: 123}
欢迎回家alex

功能改进,含参装饰器(使得可以用多种数据库)

user_list = [
    {name:alex,passwd:123},
    {name:Joey,passwd:234},
    {name:Tony,passwd:345},
]
current_dic = {username:None,login:False}
def auth(auth_type=filedb):
    def auth_func(func):
        def wrapper(*args,**kmargs):
            if current_dic[username] and current_dic[login]:
                res = func(*args, **kmargs)
                return res
            username=input(用户名:).strip()
            passwd=input(密码:).strip()
            for user_dic in user_list:
                if username == user_dic[name] and passwd == user_dic[passwd]:
                    current_dic[username] = username
                    current_dic[login] = passwd
                    res = func(*args, **kmargs)
                    return res
            else:
                print(用户名或密码错误)
        return wrapper
    return auth_func
@auth(auth_type=filedb)
def index():
    print(欢迎来到京东主页)
    pass
@auth
def home(name):
    print(欢迎回家%s %name)
    pass
@auth
def cart():
    print(购物车里有[%s,%s,%s] %(零食,书籍,衣服))
    pass
@auth
def order():
    pass
index()
print(current_dic)
home(alex)
user_list = [
    {name:alex,passwd:123},
    {name:Joey,passwd:234},
    {name:Tony,passwd:345},
]
current_dic = {username:None,login:False}
def auth(auth_type=filedb):
    def auth_func(func):
        def wrapper(*args,**kmargs):
            print(认证类型是%s %auth_type)
            if auth_type == filedb:
                if current_dic[username] and current_dic[login]:
                    res = func(*args, **kmargs)
                    return res
                username=input(用户名:).strip()
                passwd=input(密码:).strip()
                for user_dic in user_list:
                    if username == user_dic[name] and passwd == user_dic[passwd]:
                        current_dic[username] = username
                        current_dic[login] = passwd
                        res = func(*args, **kmargs)
                        return res
                else:
                    print(用户名或密码错误)
                if auth_type == ldap:
                    pass
                else:
                    print(无法识别类型)

        return wrapper
    return auth_func
@auth(auth_type=filedb)
def index():
    print(欢迎来到京东主页)
    pass
@auth(auth_type=filedb)
def home(name):
    print(欢迎回家%s %name)
    pass
@auth(auth_type=filedb)
def cart():
    print(购物车里有[%s,%s,%s] %(零食,书籍,衣服))
    pass
@auth(auth_type=filedb)
def order():
    pass
index()
print(current_dic)
home(alex)

result:
认证类型是filedb
用户名:alex
密码:123
欢迎来到京东主页
{username: alex, login: 123}
认证类型是filedb
欢迎回家alex

 

 

 

 

 


以上是关于Python装饰器的主要内容,如果未能解决你的问题,请参考以下文章

[TimLinux] Python 装饰器

python装饰器

python装饰器关键代码

Python装饰器

python之装饰器

python 装饰器