【Python基础】装饰器

详解Python装饰器

阅读目录

一、什么是装饰器

器即函数

装饰即修饰,意指为其他函数添加新功能

装饰器定义:本质就是函数,功能是为其他函数添加新功能

二 、装饰器需要遵循的原则

1、不修改被装饰函数的源代码(开放封闭原则)

2、为被装饰函数添加新功能后,不修改被修饰函数的调用方式

三、实现装饰器知识储备

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

四、高阶函数

高阶函数定义:

  1、函数接收的参数是一个函数名

  2、函数的返回值是一个函数名

  3、满足上述条件任意一个,都可称之为高阶函数

def foo():
    print('我的函数名作为参数传给高阶函数')
def gao_jie1(func):
    print('我就是高阶函数1,我接收的参数名是%s' %func)
    func()

def gao_jie2(func):
    print('我就是高阶函数2,我的返回值是%s' %func)
    return func

gao_jie1(foo)
gao_jie2(foo)
高阶函数示范
#高阶函数应用1:把函数当做参数传给高阶函数
import time
def foo():
    print('from the foo')

def timmer(func):
    start_time=time.time()
    func()
    stop_time=time.time()
    print('函数%s 运行时间是%s' %(func,stop_time-start_time))
timmer(foo)
#总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式
把函数当做参数传给高阶函数
#高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名
import time
def foo():
    print('from the foo')

def timmer(func):
    start_time=time.time()
    return func
    stop_time=time.time()
    print('函数%s 运行时间是%s' %(func,stop_time-start_time))
foo=timmer(foo)
foo()
#总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何新功能
函数返回值是函数名

高阶函数总结

1.函数接收的参数是一个函数名
  作用:在不修改函数源代码的前提下,为函数添加新功能,
  不足:会改变函数的调用方式
2.函数的返回值是一个函数名
  作用:不修改函数的调用方式
  不足:不能添加新功能

五、函数嵌套

def father(name):
    print('from father %s' %name)
    def son():
        print('from son')
        def grandson():
            print('from grandson')
        grandson()
    son()

father('熊大')

#在father 函数里面再定义son 函数 叫做函数嵌套
# def father(name):
#     print('from father %s' %name)
#     def son():
#         print('from son')
#     print(locals())     #打印当前层的局部变量
#
# father('xiong')

def father(name):
    # print('from father %s' %name)
    def son():
        print('我的爸爸是%s'%name)
        def grandson():
            name = "我自己"
            print('我的爷爷是%s'%name)
        grandson()
    son()

father('xiong')
嵌套练习1

六、闭包

'''
闭包:在一个作用域里放入定义变量,相当于打了一个包
'''
def father(name):
    def son():
        # name='alex'
        print('我爸爸是 [%s]' %name)
        def grandson():
            name='熊大'
            print('我爷爷是 [%s]' %name)
        grandson()
    son()

father('灰太狼')

七、无参装饰器

无参装饰器=高级函数+函数嵌套

基本框架

#这是实现一个装饰器最基本的框架
def timer(func):
     def wrapper():
         func()
     return wrapper

加上参数

def timer(func):
     def wrapper(*args,**kwargs):
         func(*args,**kwargs)
     return wrapper

加上功能

#这是计算函数运行时间的装饰功能
import time
def timer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        func(*args,**kwargs)
        stop_time=time.time()
        print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
    return wrapper

加上返回值 (wrapper() 函数加上return)

import time
def timer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
        return res
    return wrapper

使用装饰器

def cal(array):
    res=0
    for i in array:
        res+=i
    return res

cal=timer(cal)
cal(range(10))

语法糖 @

@timer  #@timer <===> cal=timer(cal)
def cal(array):
    res=0
    for i in array:
        res+=i
    return res

cal(range(10))

代码运行过程:

 

import time
def timmer(func): #func=test1
    def wrapper(*args,**kwargs): #test('linhaifeng',age=18)  args=('linhaifeng')  kwargs={'age':18}
        start_time=time.time()
        res=func(*args,**kwargs) #就是在运行test()         func(*('linhaifeng'),**{'age':18})
        stop_time = time.time()
        print('运行时间是%s' %(stop_time-start_time))
        return res
    return wrapper


def test(name,age):
    time.sleep(3)
    print('test函数运行完毕,名字是【%s】 年龄是【%s】' %(name,age))
    return '这是test的返回值'

test=timmer(test)
res=test('linhaifeng',age=18)  #就是在运行wrapper('linhaifeng',age=18)
print(res)

@timmer     # ===> test=timmer(test)
def test1(name,age,gender):
    time.sleep(1)
    print('test1函数运行完毕,名字是【%s】 年龄是【%s】 性别【%s】' %(name,age,gender))
    return '这是test1的返回值'

res = test1('alex',18,'male')
print(res)

补充:*args,**kwargs 传值

def test2(name,age,gender): #test2(*('alex',18,'male','x','y'),**{})
    #name,age,gender=('alex',18,'male','x','y')
    print(name)
    print(age)
    print(gender)

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

# test2('alex',18,gender='male')

test1('alex',18,'male')     #test2(*('alex',18,'male'),**{})
test1('alex',18,gender = 'male')    #test2(*('alex',18),**{"gender":'male'})
*args,**kwargs 传值

八、装饰器应用示例

import time
user_info = [
    {"name":"灰太狼",'passwd':"123"},
    {"name":"喜洋洋",'passwd':'456'},
    {"name":"红太狼",'passwd':'789'},
    {"name":"小灰灰",'passwd':'000'},
    {"name":"美羊羊",'passwd':'1314'},
    {"name":"懒洋洋",'passwd':'159'},
]
current_state = {"username":None,"login":False}

def auth_func(func):
    def wrapper(*args,**kwargs):
        if current_state["username"] and current_state["login"]:
            res = func(*args,**kwargs)
            return res
        username = input("输入用户名>>>")
        passwd = input("输入密码>>>")
        for item in user_info:
            if username == item["name"] and passwd == item["passwd"]:
                current_state["username"] = username
                current_state["login"] = True
                res = func(*args, **kwargs)
                return res
        else:
            print("输入的用户名或密码错误,请重新输入!")
    return wrapper

@auth_func  #--->index = auth_func(index)
def index():
    print('开始执行index()函数')
    time.sleep(1)
    print("欢迎来到京东主页面。。。")

@auth_func
def home(name):
    print('开始执行home()函数')
    time.sleep(1)
    print("你好啊%s,欢迎回家!"%name)

@auth_func
def shopping_car(name,goods):
    print('开始执行shopping_car()函数')
    time.sleep(2)
    print("%s的购物车里面有商品%s"%(name,goods))

index()
home("村长")
shopping_car("灰太狼",['牛奶','饼干','羊腿'])


####打印结果
输入用户名>>>喜洋洋
输入密码>>>456
开始执行index()函数
欢迎来到京东主页面。。。
开始执行home()函数
你好啊村长,欢迎回家!
开始执行shopping_car()函数
灰太狼的购物车里面有商品['牛奶', '饼干', '羊腿']
无参装饰器-综合案例
import time
f = open("filedb",'r+',encoding="utf8")
userInfo = f.readlines()
f.close()
current_state = {"username":None,"login":False}
def auth(auth_type = "filedb"):
    def auth_func(func):
        def wrapper(*args,**kwargs):
            if current_state["username"] and current_state["login"]:
                res = func(*args,**kwargs)
                return res
            username = input("输入用户名>>>")
            passwd = input("输入密码>>>")
            for item in userInfo:
                if username == eval(item)['name'] and passwd == eval(item)['passwd']:
                    current_state["username"] = username
                    current_state["login"] = True
                    res = func(*args, **kwargs)
                    return res
            else:
                print("输入的用户名或密码错误,请重新输入!")
        return wrapper
    return auth_func

@auth(auth_type="filedb")  #@auth(auth_type="filedb")--->auth_func 附加了一个auth_type参数 --->index=auth_func(index)
def index():
    print('开始执行index()函数')
    time.sleep(1)
    print("欢迎来到京东主页面。。。")

@auth(auth_type="filedb")
def home(name):
    print('开始执行home()函数')
    time.sleep(1)
    print("你好啊%s,欢迎回家!"%name)

@auth(auth_type="filedb")
def shopping_car(name,goods):
    print('开始执行shopping_car()函数')
    time.sleep(2)
    print("%s的购物车里面有商品%s"%(name,goods))

index()
home("村长")
shopping_car("灰太狼",['牛奶','饼干','羊腿'])
有参数装饰器-验证功能
{"name":"灰太狼",'passwd':"123"}
{"name":"喜洋洋",'passwd':'456'}
{"name":"红太狼",'passwd':'789'}
{"name":"小灰灰",'passwd':'000'}
{"name":"美羊羊",'passwd':'1314'}
{"name":"懒洋洋",'passwd':'159'}
有参数装饰器-filedb文件

九、超时装饰器

 

十、Python内置的装饰器

链接: 静态属性(@property)、类方法(@classmethod)、静态方法(@staticmethod)

 

参考:

https://www.cnblogs.com/linhaifeng/articles/6140395.html#_label8

posted @ 2019-05-14 11:21  XJT2019  阅读(210)  评论(0编辑  收藏  举报