Python3 装饰器解析

第6章 函数

很多人学习python,不知道从何学起。
很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
很多已经做案例的人,却不知道如何去学习更加高深的知识。
那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!
QQ群:1097524789

  • 6.1 函数的定义和调用
  • 6.2 参数传递
  • 6.3 函数返回值
  • 6.4 变量作用域
  • 6.5 匿名函数(lambda)
  • 6.6 递归函数
  • 6.7 迭代器
  • 6.8 生成器
  • 6.9 装饰器

6.9 装饰器

装饰器本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,它也不会改变函数或类的调用方式。

它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景,装饰器是解决这类问题的绝佳设计。有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码到装饰器中并继续重用。

概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

装饰器的语法是将@装饰器名,放在被装饰对象上面。

有两类装饰器:函数装饰器、类装饰器

# 函数装饰器的语法
@dec
def func():
    pass
参数说明:
@称为语法糖
dec:装饰器名字
func:被装饰的函数名

在介绍装饰器之前,先明确几个概念及原则:

原则:

Python程序是从上往下顺序执行的,而且碰到函数的定义代码块是不会立即执行的,只有等到该函数被调用时,才会执行其内部的代码块。

如果一个函数定义了两次,那么后面定义的会覆盖前面的定义。

在Python中代码的放置位置是有区别的,不能随意摆放,通常函数体要放在调用的语句之前。

概念:

函数名、函数体、返回值,函数的内存地址、函数名加括号、函数名被当作参数、函数名加括号被当作参数、返回函数名、返回函数名加括号。

# 加操作:无参数
import time


def timer(func):
    def inner():
        t1 = time.time()
        func()
        t2 = time.time()
        return t2 - t1

    return inner


@timer
def add():
    a = 1
    b = 1
    time.sleep(1)
    c = a + b
    print(c)
    return c


add = add()
print(add)

函数名: timer 、 add 、 inner

函数体:除def那一行外的部分

返回值: return后面的表达式

函数的内存地址: id(add) 、 id(outer) 等等

函数名加括号:对函数进行调用,比如 add() 、 timer(func)

函数名作为参数: timer(func) 中的 func 本身是个函数,但作为参数被传递给了timer函数

函数名加括号被当做参数:其实就是先调用函数,再将它的返回值当做别的函数的参数,例如 timer(add())

返回函数名: return inner

返回函数名加括号: return inner() ,其实就是先执行inner函数,再将其返回值作为别的函数的返回值。

一个装饰器例子:

‘‘‘
1、@timer,称为语法糖,其作用是将被装饰函数add的函数名作为实参传给装饰器timer函数的形参func,传函数名实际传的是内存指向;
2、函数timer内又嵌套了inner函数,返回值是函数名inner,必须要明确的是,传进去函数名add,返回来inner函数名,结果就是add和inner共同指向在内存中定义inner的起始地址,而此时形参func指向在内存定义add的起始地址,可在调试程序过程中通过id方法打印查看add和inner所指向的内存地址的变化情况。
明确这两点,装饰器就不难理解了。
‘‘‘
# 加操作:无参数
import time


def timer(func):
    def inner():
        t1 = time.time()
        func()
        t2 = time.time()
        return t2 - t1

    return inner


@timer
def add():
    a = 1
    b = 1
    time.sleep(1)
    c = a + b
    print(c)
    return c


add = add()
print(add)
# 加操作:位置参数
import time


def timer(func):
    def inner(a, b):
        t1 = time.time()
        func(a, b)
        t2 = time.time()
        return t2 - t1

    return inner


@timer
def add(a, b):
    # a = 1
    # b = 1
    time.sleep(1)
    c = a + b
    print(c)
    return c


add = add(1, 1)
print(add)
# 加操作:可变参数
import time


def timer(func):
    def inner(*args):
        t1 = time.time()
        func(*args)
        t2 = time.time()
        return t2 - t1

    return inner


@timer
def add(a, b):
    # a = 1
    # b = 1
    time.sleep(1)
    c = a + b
    print(c)
    return c


add = add(1, 1)
print(add)
# 加减乘除操作:可变参数
import time


def timer(func):
    def inner(*args):
        t1 = time.time()
        func(*args)
        t2 = time.time()
        return t2 - t1

    return inner


@timer
def add(a, b):
    # a = 1
    # b = 1
    time.sleep(1)
    c = a + b
    print(c)
    return c


@timer
def plus(a, b):
    # a = 1
    # b = 1
    time.sleep(2)
    c = a - b
    print(c)
    return c


@timer
def multi(a, b):
    # a = 1
    # b = 1
    time.sleep(3)
    c = a * b
    print(c)
    return c


@timer
def div(a, b):
    # a = 1
    # b = 1
    time.sleep(4)
    c = a / b
    print(c)
    return c


add = add(1, 1)
print(add)
plus = plus(2, 1)
print(plus)
multi = multi(3, 1)
print(multi)
div = div(4, 1)
print(div)