函数(四)——装饰器

今日内容概要:

一、巩固复习

二、装饰器(掌握)

内容详解:

一、巩固复习

1、一定要熟记的格式:

def register(name, age,gender="male"):
    print(name, age, gender)

def wrapper(*args,**kwargs):
    index(*args,**kwargs)

#根据register,wrapper内必须传三个实参,鉴于形参gender已定义,可以默认不传也可传值
wrapper(???)

2、函数体传参的两种方式

 (1)直接传参(直接通过参数的形式为函数体传)

def func(x):
    print(x)

func(1)
func(2)
func(3)

 (2)闭包传参(把它想要的参数值包给它)

def outter(x):
    # x = 1
    def func():
        print(x)
    return func

f1=outter(1)
f2=outter(2)

3、基于函数对象的概念优雅地取代if判断多分支

def foo():
    print('foo')

def bar():
    print('bar')

dic={
    'foo':foo,
    'bar':bar,
}
while True:
    choice=input('>>: ').strip()
    if choice in dic:
        dic[choice]()

4、名称空间的名字查找顺序

局部-》外层套的局部-》外层套的局部-》....-》全局-》内置

5、强调强调强调

名称空间的"嵌套关系"是函数定义阶段、也就是检测语法的时候就确定的,与调用为无关

6、global的作用

声明变量是来自全局的,如果要修改必须在全局找变量赋值,不能在局部,找不到就报错

7、nonlocal的作用

声明变量是来自局部的,如果要修改必须在自己函数的外一层找,找不到再在外一层找,但不能在全局或自己函数内找,找不到就报错

8、闭包函数=函数对象+函数嵌套定义+名称空间与作用域

基本模板:
def outter():
   x=123
   def inner():
       x
   return inner # 函数是第一等公民、第一类对象

res=outter()
res()

 

二、装饰器

1、什么是装饰器
器指的是工具/功能
装饰指的是为被装饰对象添加额外的功能

大白话:定义装饰器就是定义了一个函数,该函数就是用来为其他函数添加额外的功能的

2、为何要用装饰器
程序的开发需要遵循一个原则:开放封闭原则
开放:指的是对拓展功能开放
封闭:指的是对修改源代码封闭

装饰器就是在不修改被装饰对象源代码以及调用方式的前提下为被装饰对象添加上新功能

3、如何用装饰器
# 1、装饰器初探
import time

def index(x, y):
    time.sleep(3)
    print('index===>', x, y)


# index(1,2)


def home(name):
    time.sleep(2)
    print('home====>', name)


# home("egon")

def outter():
    x = index

    def wrapper(a, b):
        start_time = time.time()
        x(a, b)
        stop_time = time.time()
        print("run time is :%s" % (stop_time - start_time))

    return wrapper  # 千万不要加括号


index = outter()  # f=wrapper

index(1, 2)  # wrapper()
# 1、装饰器初探
# 2、装饰器改进1

import time

def index(x, y):
    time.sleep(3)
    print('index===>', x, y)

def home(name):
    time.sleep(2)
    print('home====>', name)

def outter(x):
    # x = home
    def wrapper(*args,**kargs):
        start_time = time.time()
        x(*args,**kargs) # x("egon")
        stop_time = time.time()
        print("run time is :%s" % (stop_time - start_time))
    return wrapper  # 千万不要加括号

index = outter(index)  # index=wrapper
home = outter(home)  # home=wrapper


index(1, 2)  # wrapper(1,2)
home("egon")  # wrapper("egon")
# 2、装饰器改进1
# 3、装饰器改进2

import time


def index(x, y):
    time.sleep(3)
    print('index===>', x, y)
    return 456

def home(name):
    time.sleep(2)
    print('home====>', name)
    return 123


def outter(x):
    # x = home
    def wrapper(*args, **kargs):
        start_time = time.time()
        res = x(*args, **kargs)  # x("egon")
        stop_time = time.time()
        print("run time is :%s" % (stop_time - start_time))
        return res
    return wrapper  # 千万不要加括号

index = outter(index)  # index=wrapper
home = outter(home)  # home=wrapper

res1 = index(1, 2)  # wrapper(1,2)
res2 = home("egon")  # wrapper("egon")
print("====>",res1)
print("====>",res2)
# 3、装饰器改进2
# 4、语法糖

import time

def outter(x):
    # x = home
    def wrapper(*args, **kargs):
        start_time = time.time()
        res = x(*args, **kargs)  # x("egon")
        stop_time = time.time()
        print("run time is :%s" % (stop_time - start_time))
        return res

    return wrapper  # 千万不要加括号


@outter  # index = outter(index)  # index=wrapper
def index(x, y):
    time.sleep(3)
    print('index===>', x, y)
    return 456


@outter  # home = outter(home)  # home=wrapper
def home(name):
    time.sleep(2)
    print('home====>', name)
    return 123


res1 = index(1, 2)  # wrapper(1,2)
res2 = home("egon")  # wrapper("egon")
print("====>", res1)
print("====>", res2)
# 4、语法糖
# 5、装饰器的模板

def outter(func):
    def wrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        return res
    return wrapper

def timmer(func):
    def wrapper(*args, **kwargs):
        start=time.time()
        res = func(*args, **kwargs)
        stop=time.time()
        print(stop -start)
        return res
    return wrapper

def auth(func):
    def wrapper(*args, **kwargs):
        name = input("请输入您的账号:").strip()
        pwd = input("请输入您的账号:").strip()
        if name == "egon" and pwd == "123":
            print('登录成功')
            res = func(*args, **kwargs)
            return res
        else:
            print("账号密码错误")
    return wrapper

@auth
def index(x, y):
    time.sleep(1)
    print('index===>', x, y)
    return 456

@auth
def home(name):
    time.sleep(0.5)
    print('home====>', name)
    return 123

index(1,2)
home("egon")
# 5、装饰器的模板
# 6、wraps

from functools import wraps

def timmer(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start=time.time()
        res = func(*args, **kwargs)
        stop=time.time()
        print(stop -start)
        return res
    # wrapper.__name__ = func.__name__
    # wrapper.__doc__ = func.__doc__
    return wrapper

@timmer # index=timmer(index) # index=wrapper
def index(x, y):
    """
    这是index函数的文档注释
    """
    time.sleep(1)
    print('index===>', x, y)
    return 456


# index(1,2)
# print(index.__name__)
help(index)
# 6、wraps装饰器

语法糖的作用:写在被装饰函数正上方,用 @+装饰器函数名outter ,调用一下装饰器函数outter ,把被装饰函数index传进来,将返回值wrapper覆盖给原函数

  4、无参装饰器(两层)

import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print('run time is %s' %(stop_time-start_time))
        return res
    return wrapper

@timmer
def foo():
    time.sleep(3)
    print('from foo')
foo()
#无参装饰器

  5、有参装饰器(三层)

def auth(driver='file'):
    def auth2(func):
        def wrapper(*args,**kwargs):
            name=input("user: ")
            pwd=input("pwd: ")

            if driver == 'file':
                if name == 'egon' and pwd == '123':
                    print('login successful')
                    res=func(*args,**kwargs)
                    return res
            elif driver == 'ldap':
                print('ldap')
        return wrapper
    return auth2

@auth(driver='file')
def foo(name):
    print(name)

foo('egon')
#有参装饰器

  6、最完整的装饰器模板

#必须要牢记!!!

from functools import wraps #这一行和@wraps(func)可以不加,执行后只是少了文本注释 def outter(func): #func指的就是被装饰对象 @wraps(func) def wrapper(*args, **kwargs): #wrapper就是给被装饰对象添加功能 res = func(*args, **kwargs) return res return wrapper #返回的wrapper一定不要加括号
原文地址:https://www.cnblogs.com/guojieying/p/13160107.html