Python - 函数与装饰器Decorator的原理

本文通过实例来讲述函数与装饰器之间的关系,理解Python编程中装饰器这一概念。Python中,装饰器是针对函数而言的,都是对象,可以接受参数,也可以作为参数传递。装饰器包含另一个函数,扩展了该函数的用法,并返回该函数的值。

装饰器避免了代码中不必要的重复,在开发过程中可以预先做一些设置,比如设置计时器、日志处理等;也可以设置有效性和检查运行时。

接下来先看看简单的函数及其调用!

函数及其调用

def greet():
    print("小明,你好!")
    
greet_name = greet
greet_name()

输出结果:小明,你好!

从以上代码中可以看出,每项内容都是对象,可以给一个变量赋值,反之,必要的时候可以把函数作为变量的赋值。这一点对理解装饰器很重要!

下面看一个函数作为另一个函数的返回的例子:

def greet():
    def greeting_at_dawn():
        print("早上好!")
        
    return greeting_at_dawn

salute = greet()
salute()

以上代码运行结果:早上好!

在Python编程中,内部函数可以从外部函数中返回,这是函数编程的一个基本概念。

接下来看看函数作为另一个函数的参数进行传递,

def greet_person(func):
    print("你好!", end=' ')
    func()

def say_person():
    print("小明")

greet_person(say_person)

输出结果:你好! 小明

理解以上三个简单的例子,有助于在编程中正确地使用装饰器。


装饰器的工作原理

装饰器是一个函数,那么定义该函数就是定义相应的装饰器,有一个外部打包函数和一个内嵌函数。

一个装饰器的基本编码如下:

def increase_number(func):
    def increase_by_one():
        print("数值按 1 递增 ...")
        number_plus_one = func()  + 1
        return number_plus_one
    return increase_by_one 
    
def get_number():
    return 5
    
get_new_number = increase_number(get_number)
print(get_new_number())

输出结果:

数值按 1 递增 ...


6

以上代码中,外部函数increase_number就是装饰器,接收函数func; 打包函数是increase_by_one,其中包含函数get_number;该装饰器increase_number赋值给另一个变量。这就是装饰器的基本语法,但是通常会使用以下更简洁的表示方法:

def increase_number(func):
    def increase_by_one():
        print("数值按 1 递增 ...")
        number_plus_one = func()  + 1
        return number_plus_one
    return increase_by_one 
    
@increase_number    
def get_number():
    return 5

print(get_number())

从以上代码可以看出,装饰器扩展了所需函数参数的功能。

带参数的装饰器

以下代码中,需要把多个参数传递给装饰器:

def multiply_numbers(func):
    def multiply_two_numbers(num1, num2):
        print("两数相乘: {} 和 {}".format(num1, num2))
        return func(num1, num2)
        
    return multiply_two_numbers

@multiply_numbers
def multiply_two_given_numbers(num1, num2):
    return f'{num1} * {num2} = {num1 * num2}'
    
print(multiply_two_given_numbers(3, 4))

运行结果:

两数相乘: 3 和 4

3 * 4 = 12

把多个参数传递给内嵌函数,可以使装饰器用起来更灵活!传递多个参数还可以用以下方法:

def decorator_func(decorated_func):
    def wrapper_func(*args, **kwargs):
        print(f'本函数有 {len(args)} 占位参数和 {len(kwargs)} 关键字参数')
        return decorated_func(*args, **kwargs)
        
    return wrapper_func

@decorator_func
def names_and_age(age1, age2, name1='李冰', name2='王峰'):
    return f'{name1} {age1} 岁, {name2} {age2} 岁'
    
print(names_and_age(12, 15, name1="小明", name2="小倩"))

运行结果:

本函数有 2 占位参数和 2 关键字参数

小明 12 岁, 小倩 15 岁

以上代码中,*args 构成了一个元组,用于迭代占位参数 ,而**kwargs 构成了一个关键字的词典。

多个装饰器并用

在编程中针对某个函数,可以同时并用多个装饰器,看以下代码实例:

def increase_decorator(func):
    def increase_by_two():
        print('数值按 2 递增')
        new_number = func()
        return new_number + 2
        
    return increase_by_two
    

def decrease_decorator(func):
    def decrease_by_one():
        print('数值按 1 递减')
        new_number = func()
        return new_number - 1
        
    return decrease_by_one
    
@increase_decorator
@decrease_decorator
def get_number():
    return 5
    
print(get_number())

运行结果:

数值按 2 递增

数值按 1 递减

6

(本文完)

更多有关Python装饰器的用法,可阅读 python - 常用的装饰器 decorator 有哪些?

展开阅读全文

页面更新:2024-04-15

标签:函数   赋值   数值   变量   早上好   实例   你好   原理   关键字   参数   代码

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top