在 Python 中使用裝飾器時如何保留函數簽名?

DDD
發布: 2024-10-17 16:59:58
原創
445 人瀏覽過

How to Preserve Function Signatures When Using Decorators in Python?

Preserving Signatures of Decorated Functions

Decorators are a powerful tool for enhancing the functionality of Python functions. However, they can sometimes obscure the original function's signature. This can be problematic for documentation, debugging, and automated tools.

Problem:

Consider a generic decorator that converts all arguments to integers:

<code class="python">def args_as_ints(f):
    def g(*args, **kwargs):
        args = [int(x) for x in args]
        kwargs = dict((k, int(v)) for k, v in kwargs.items())
        return f(*args, **kwargs)
    return g</code>
登入後複製

While the decoration works as expected, the decorated function's signature is replaced with "args, *kwargs", losing information about the original arguments.

Workarounds:

Several workarounds exist, but none are fully satisfactory:

  • Manually copying the signature into the docstring.
  • Creating a new decorator for each specific signature.
  • Manually constructing the decorated function with exec.

Solution:

decorator module offers an elegant solution:

<code class="python">import decorator

@decorator.decorator
def args_as_ints(f, *args, **kwargs):
    args = [int(x) for x in args]
    kwargs = dict((k, int(v)) for k, v in kwargs.items())
    return f(*args, **kwargs)</code>
登入後複製

This decorator preserves the original function's signature by passing it as arguments to the wrapped function.

Improved Decorator:

<code class="python">@args_as_ints
def funny_function(x, y, z=3):
    """Computes x*y + 2*z"""
    return x*y + 2*z</code>
登入後複製

Now, the decorated function funny_function retains its original signature:

>>> help(funny_function)
Help on function funny_function in module __main__:

funny_function(x, y, z=3)
    Computes x*y + 2*z
登入後複製

Python 3.4+:

For Python 3.4 and above, functools.wraps provides a similar solution:

<code class="python">import functools

def args_as_ints(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        args = [int(x) for x in args]
        kwargs = dict((k, int(v)) for k, v in kwargs.items())
        return func(*args, **kwargs)
    return wrapper</code>
登入後複製

By using these techniques, decorators can enhance function functionality while preserving their original signatures, ensuring clarity and consistency in the codebase.

以上是在 Python 中使用裝飾器時如何保留函數簽名?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板