Python基础(六)-装饰器

一、高阶函数

1.1、高阶函数的定义

  • 函数接受的是一个函数名
  • 函数的返回值是一个函数名
  • 满足上述条件的任意一个,都可以被称之为高阶函数
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.2、高阶函数的应用

1)将函数名传递给高阶函数

import time
def foo():
    time.sleep(3)
    print('你好')

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

test(foo)

你好
函数运行时间是  3.0009939670562744

#我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数test(foo),改变了函数的调用方式

2)高阶函数返回的是一个函数名

#没有改变函数的调用方式,但多运行了一次,不合格
import time
def foo():
    time.sleep(3)
    print('你好')

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

foo = test(foo)   #此时已经调用了foo,下面又调用了一次
foo()

你好
函数运行时间是  3.000460386276245
你好

3)没有修改被修饰函数的源代码,也没有修改被修饰函数的调用方式,但是也没有为被修饰函数添加新功能

import time
def foo():
    time.sleep(3)
    print('来自foo')

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

foo=timer(foo)
foo()

来自foo

1.3、高阶函数总结

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

  作用:在不修改函数源代码的前提下,为函数添加新功能,

  不足:会改变函数的调用方式

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

  作用:不修改函数的调用方式

  不足:不能添加新功能

二、函数的嵌套

2.1、函数嵌套定义

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

father('AAA')

2.2、闭包

def father(auth_type):
    # print('from father %s' %name)
    def son():
        # name='linhaifeng_1'
        # print('我的爸爸是%s' %name)
        def grandson():
            print('我的爷爷是%s' %auth_type)
        grandson()
    # print(locals())
    son()
# father('A')
father('filedb')

#我的爷爷是filedb

三、装饰器简介

本质上是函数,功能是为其他han书添加新功能

3.1、装饰器遵循的原则

  • 不修改被装饰函数的源代码(开放封闭原则)
  • 为被装饰的添加新功能后,不修改被装饰函数的调用方式

3.2、实现装饰器的知识储备

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

3.3、装饰器的基本实现

import time
def timmer(func): #func=test
    def wrapper():
        # print(func)
        start_time=time.time()
        func() #就是在运行test()
        stop_time = time.time()
        print('运行时间是%s' %(stop_time-start_time))
    return wrapper

@timmer #test=timmer(test)
def test():
    time.sleep(3)
    print('test函数运行完毕')
test()

# res=timmer(test)  #返回的是wrapper的地址
# res()  #执行的是wrapper()

# test=timmer(test)  #返回的是wrapper的地址
# test()  #执行的是wrapper()

#  @timmer  就相当于 test=timmer(test)

3.4、函数添加返回值

import time
def timmer(func): #func=test
    def wrapper():
        start_time=time.time()
        res=func() #就是在运行test()
        stop_time = time.time()
        print('运行时间是%s' %(stop_time-start_time))
        return res
    return wrapper

@timmer #test=timmer(test)
def test():
    time.sleep(3)
    print('test函数运行完毕')
    return '这是test的返回值'

res=test()  #就是在运行wrapper
print(res)

运行时间是3.000176191329956
这是test的返回值

3.5、函数添加参数

import time
def timmer(func): #func=test1
    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


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

test1('AA',18,'male')

3.6、装饰的应用

user_list=[
    {'name':'alex','passwd':'123'},
    {'name':'linhaifeng','passwd':'123'},
    {'name':'wupeiqi','passwd':'123'},
    {'name':'yuanhao','passwd':'123'},
]
current_dic={'username':None,'login':False}

def auth(auth_type='filedb'):
    def auth_func(func):
        def wrapper(*args,**kwargs):
            print('认证类型是',auth_type)
            if auth_type == 'filedb':
                if current_dic['username'] and current_dic['login']:
                    res = func(*args, **kwargs)
                    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']=True
                        res = func(*args, **kwargs)
                        return res
                else:
                    print('用户名或者密码错误')
            elif auth_type == 'ldap':
                print('鬼才特么会玩')
                res = func(*args, **kwargs)
                return res
            else:
                print('鬼才知道你用的什么认证方式')
                res = func(*args, **kwargs)
                return res

        return wrapper
    return auth_func

@auth(auth_type='filedb') #auth_func=auth(auth_type='filedb')-->@auth_func 附加了一个auth_type  --->index=auth_func(index)
def index():
    print('欢迎来到京东主页')

@auth(auth_type='ldap')
def home(name):
    print('欢迎回家%s' %name)
#
@auth(auth_type='sssssss')
def shopping_car(name):
    print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃'))

# print('before-->',current_dic)
# index()
# print('after--->',current_dic)
# home('产品经理')
shopping_car('产品经理')
原文地址:https://www.cnblogs.com/hujinzhong/p/11470878.html