gpt4 book ai didi

python - 为什么在发生参数错误时不使用装饰函数的名称?

转载 作者:行者123 更新时间:2023-12-03 21:13:15 26 4
gpt4 key购买 nike

我明白 functools.wraps 的目的- 继承像 __doc__ 这样的属性, __name__等。但我正在努力解释为什么会发生以下情况。我在 Python 中有这个装饰器函数:

from functools import update_wrapper
class Environment:
...

def requires_environment(function: Callable) -> Callable:
def wrapped_function(*args, environment, **kwargs):
if not isinstance(environment, Environment):
raise TypeError("The environment keyword argument must be of type Environment.")
kwargs["environment"] = environment
return function(*args, **kwargs)
update_wrapper(wrapped_function, function)
return wrapped_function

然后我用它装饰一个函数:
@requires_environment
def function_with_args(arg1, arg2, environment):
pass

当我不提供 environment我的关键字 function_with_args ,我希望错误消息应该是 TypeError: function_with_args() :
function_with_args(1, 2, Environment.PROD)

我得到
TypeError: wrapped_function() missing 1 required keyword-only argument: 'environment'

为什么是 wrapped_function显示而不是 function_with_args ?如果我打印摆脱 @ 的语法糖装饰器并打印函数名称,即使在装饰之后,正确地说新包装的函数名称是 function_with_args :
function_with_args = requires_environment(function_with_args)
print("After", function_with_args.__name__) # After function_with_args
function_with_args(1, 2, Environment.PROD)

然而我仍然看到我的 wrapped_function名称在 TypeError .为什么会出现这种情况?

以下是我完整的可重现示例:
from time import perf_counter
from typing import Callable
from enum import Enum
from functools import update_wrapper

class Environment(Enum):
PROD = "PROD"
STAGING = "STAGING"
DEV = "DEV"


def requires_environment(function: Callable) -> Callable:
def wrapped_function(*args, **kwargs):
if "environment" not in kwargs:
raise TypeError(f"{function.__name__}() missing 1 required keyword-only argument: 'environment'")

if not isinstance(kwargs['environment'], Environment):
raise TypeError("The environment keyword argument must be of type Environment.")

return function(*args, **kwargs)

update_wrapper(wrapped_function, function)

return wrapped_function


@requires_environment
def function_with_args(arg1, arg2, environment):
print(f"Inside function {function_with_args.__name__}")
print(f"Docstrings: {function_with_args.__doc__}")

function_with_args(1, 2, Environment.PROD)

最佳答案

此错误消息使用代码对象的名称,而不是函数对象的名称。代码对象不能重命名;即使经过 functools.update_wrapper设置函数的 __name__ , 函数的代码对象的 co_name还在wrapped_function .您可以通过检查 function_with_args.__code__.co_name 看到这一点。 .

这种行为是 scheduled to change在 Python 3.10 中使用函数的 __qualname__ , 以更好地消除不同类的同名方法的歧义。

关于python - 为什么在发生参数错误时不使用装饰函数的名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62369153/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com