python装饰器底层原理

什么是装饰器

装饰器是Python中的一种特殊函数,主要用于修改或扩展其他函数或方法的功能,而无需修改函数本身的代码。它们通常通过在函数定义前加上@装饰器名称来使用。

@decorator_function
def my_function():
    pass
 
 

装饰器的基本结构

一个基本的装饰器包含一个函数,它接受另一个函数作为参数,并返回一个新的函数。这个新的函数通常会在调用时执行一些附加操作,然后调用原始函数。

def simple_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper
​
 
 

使用该装饰器:

@simple_decorator
def say_hello():
    print("Hello!")

say_hello()
​
 
 

输出:

Something is happening before the function is called.
Hello!
Something is happening after the function is called.
​
 
 

装饰器的底层原理

为了理解装饰器的底层原理,我们需要了解以下几个方面:

1. 函数是对象

在Python中,函数是第一类对象。这意味着函数可以作为参数传递给另一个函数,可以作为另一个函数的返回值,也可以赋值给变量。

def foo():
    print("Hello from foo")

bar = foo
bar()
​
 
 

输出:

Hello from foo
​
 
 

2. 闭包

闭包是一种函数,它保留了定义它的环境中的变量。装饰器利用了闭包来包装函数并添加额外的功能。

def outer_func(msg):
    def inner_func():
        print(msg)
    return inner_func

hi_func = outer_func("Hi")
hi_func()
​
 
 

输出:

Hi
​
 
 

3. 高阶函数

装饰器本质上是高阶函数,它们接受函数作为参数,并返回一个新函数。

def decorator_function(original_function):
    def wrapper_function():
        print("Wrapper executed this before {}".format(original_function.__name__))
        return original_function()
    return wrapper_function

@decorator_function
def display():
    print("display function ran")

display()
​
 
 

输出:

Wrapper executed this before display
display function ran
​
 
 

常见装饰器模式

无参数装饰器

这是最基本的装饰器模式。它不接受任何参数,只接受一个函数作为参数。

def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper
​
 
 

带参数的装饰器

带参数的装饰器可以接受额外的参数。实现这种装饰器时,需要再嵌套一层函数。

def decorator_with_args(arg1, arg2):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(f"Arguments passed to decorator: {arg1}, {arg2}")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@decorator_with_args("Hello", "World")
def say_hello():
    print("Hello!")

say_hello()
​
 
 

输出:

Arguments passed to decorator: Hello, World
Hello!
​
 
 

类装饰器

类装饰器通过实现 __call__方法,可以像函数装饰器一样工作。

class ClassDecorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("ClassDecorator: Before the function call.")
        result = self.func(*args, **kwargs)
        print("ClassDecorator: After the function call.")
        return result

@ClassDecorator
def say_hello(name):
    print(f"Hello, {name}!")

say_hello("Alice")
​
 
 

输出:

ClassDecorator: Before the function call.
Hello, Alice!
ClassDecorator: After the function call.
​
 
 

装饰器的实际应用

日志记录

装饰器可以用于记录函数调用的日志。

def log_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Function {func.__name__} called with arguments {args} and keyword arguments {kwargs}")
        return func(*args, **kwargs)
    return wrapper

@log_decorator
def add(x, y):
    return x + y

result = add(5, 3)
​
 
 

输出:

Function add called with arguments (5, 3) and keyword arguments {}
​
 
 

访问控制与权限验证

装饰器可以用于检查用户是否具有执行某些操作的权限。

def require_authentication(func):
    def wrapper(user, *args, **kwargs):
        if not user.is_authenticated:
            print("User is not authenticated.")
            return
        return func(user, *args, **kwargs)
    return wrapper

@require_authentication
def view_profile(user):
    print(f"Displaying profile for {user.name}")

# 假设User类和user对象已经定义
view_profile(user)
​
 
 

缓存

装饰器可以用于缓存函数的结果,提高性能。

def cache(func):
    cached_results = {}

    def wrapper(*args):
        if args in cached_results:
            return cached_results[args]
        result = func(*args)
        cached_results[args] = result
        return result

    return wrapper

@cache
def compute_square(n):
    return n * n

print(compute_square(4))
print(compute_square(4))  # 这次将使用缓存结果
posted @   东绕城  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示