Python-Basis-9th

周四,晴,记录生活分享点滴

参考博客:https://www.cnblogs.com/yuanchenqi/articles/5830025.html

推荐阅读:https://www.runoob.com/w3cnote/python-func-decorators.html

Python版本:3.5

装饰器前期

作用域

https://www.cnblogs.com/chungzhao/p/12973075.html  5.0

函数即对象

函数对象的调用比其它对象多了一个(),foo,bar与a,b一样都是个变量名

只有函数加载到内存才可以被调用

1. 可以被赋给其他变量 

def foo():
    print('foo')
bar=foo
bar()
foo()
print(id(foo),id(bar))  #4321123592 4321123592

2. 可以被定义在另外一个函数内(作为参数&作为返回值)

# *******函数名作为参数**********
def foo(func):
    print('foo')
    func()

def bar():
    print('bar')

foo(bar)
# foo  bar


# *******函数名作为返回值*********
def foo():
    print('foo')
    return bar

def bar():
    print('bar')

b = foo()
b()
# foo  bar

函数的嵌套以及闭包

嵌套函数 

name = "Chung"

def change_name():
    name = "Chung2"

    def change_name2():
        name = "Chung3"
        print("第3层打印", name)  ## 第3层打印 Chung3

    change_name2()  # 调用内层函数
    print("第2层打印", name)  ## 第2层打印 Chung2

change_name()
print("最外层打印", name)  ## 最外层打印 Chung

# 各个 print 与 函数 位于同一级别

闭包函数

https://blog.csdn.net/weixin_44141532/article/details/87116038

闭包格式:

def 外层函数(参数):
    def 内层函数():
        print("内层函数执行", 参数)

    return 内层函数


内层函数的引用 = 外层函数("传入参数")
内层函数的引用()

闭包举例:

def func(a, b):  #1.外函数func有接收参数 a=2,b=3
    def line(x):  #2.内函数line接收参数x=5
        return a * x - b  #3.在内函数体中计算了a*x-b 即 2×5-3的值作为返回值

    return line  #4.外函数返回内函数的引用(这里的引用指的是内函数line在内存中的起始地址,即第二、三行)  #5.最终调用内函数line()得到返回值7

line = func(2, 3)
print(line(5))

# 7

 小结:闭包的核心是在返回时的引用,引用的是自己里面的那一层,这一层在内存中。

 

装饰器概念

作用

装饰器可以让其他函数在不需要修改代码的前提下增加额外的功能,抽离出大量与函数功能本身无关的雷同代码并继续重用。

简要概括是为已经存在的对象添加额外的功能

返回值

装饰器的返回值也是一个函数对象

应用场景

经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等应用场景

 

简单装饰器

常规

通过 show_time(foo) 返回一个函数对象,这个函数对象内是核心业务(干活儿的)函数:执行func()与装饰函数时间计算

import time
# ------------------------------------- #
def show_time(func):
    def wrapper():
        start_time=time.time()
        func()
        end_time=time.time()
        print('spend %s'%(end_time-start_time))
 
    return wrapper

# ------上面是装饰器函数,下面是功能函数----- #

def foo():
    print('hello foo')
    time.sleep(3)
# -------------------------------------- #
foo=show_time(foo)
foo()

@ 语法糖

避免再一次赋值操作

省去foo=show_time(foo)或者bar = show_time(bar)这句,直接调用foo()或者bar()得到结果

import time
 
def show_time(func):
    def wrapper():
        start_time=time.time()
        func()
        end_time=time.time()
        print('spend %s'%(end_time-start_time))
 
    return wrapper  # wrapper为闭包函数
 
@show_time   #foo=show_time(foo)
def foo():
    print('hello foo')
    time.sleep(3)
 
 
@show_time  #bar=show_time(bar)
def bar():
    print('in the bar')
    time.sleep(2)
 
foo()
print('***********')
bar()

@show_time的作用是指在执行业务逻辑foo()时,执行的代码由粉框部分转到蓝框部分

被装饰函数的参数

给功能函数加参数

#***********不定长参数**************
import time

def show_time(func):

    def wrapper(*args,**kwargs):
        start_time=time.time()
        func(*args,**kwargs)
        end_time=time.time()
        print('spend %s'%(end_time-start_time))

    return wrapper

@show_time   #add=show_time(add)
def add(*args,**kwargs):  # 给功能函数加参数

    time.sleep(1)
    sum=0
    for i in args:
        sum+=i
    print(sum)

add(2,4,8,9)

带参数的装饰器

在上面的装饰器调用中,比如@show_time,该装饰器唯一的参数就是执行业务的函数

装饰器的语法允许我们在调用时,提供其它参数,比如@decorator(a),可以继续添加参数来实现更多的功能

import time
def logger(flag=''):  # 多增加了一个函数 = 多增加了一个功能:打印'文件目录'
    def show_time(f):
        def inner(*x, **y):
            start = time.time()
            f(*x, **y)
            end = time.time()
            print('spend %s' % (end - start))

            if flag == 'true':
                print('日志记录')  #新增的功能

        return inner

    return show_time

@logger('true')  # 与if flag == 'true'相对应
def add(*a, **b):
    time.sleep(1)
    sums=0
    for i in a:
        sums += i
    print(sums)

add(1, 2, 5)  #8  spend 1.0103797912597656  日志记录


@logger('')  # 如果没有输入true,不会打印日志记录
def bar():
    time.sleep(2)
    print('hello')
bar()  # hello  spend 2.008728265762329
原文地址:https://www.cnblogs.com/chungzhao/p/12982607.html