python decorator不接受函数的参数

2024-05-29 02:33:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在学习python,而且我被困在了装饰程序中
我的理解是,装饰程序向函数添加功能
我做了一个简单的函数来检查一个数字是否为偶数
然后是一个装饰器,它把绝对值加到它上面

def decorate(func):
    def is_even_new(*args,**kwargs):
        num = abs(*args,**kwargs)
        func(num)
    return is_even_new()

@decorate 
def is_even(x):
    if x%2 == 0:
        return True
    else:
        return False

is_even(8)

但我一直得到一个类型错误:abs()只接受一个参数(给定0)
代码中是否有错误,或者我对decorators的理解是错误的


Tags: 函数程序newreturnisdef错误args
3条回答

修饰函数时,应返回修饰函数本身:

def decorate(func):
    def is_even_new(*args,**kwargs):
        num = abs(*args,**kwargs)
        func(num)

    return is_even_new

而不是调用修饰函数并返回:

def decorate(func):
    def is_even_new(*args,**kwargs):
        num = abs(*args,**kwargs)
        func(num)

    return is_even_new()

(注意额外的括号)。在最后一个示例中,当您使用@decorate装饰函数时,装饰器定义这个内部函数is_even_new,然后,它不返回后者,而是尝试不带参数地调用它:is_even_new()。这也是为什么TypeErrorabs需要(恰好)一个参数,但您没有给它任何参数

请记住,Python中的函数与其他对象一样(“一等公民”),因此您可以直接通过它们的名称引用它们

另外,作为一项建议,如果您知道用@decorate修饰的函数将只接受一个参数(如is_even),请不要使用变量参数和关键字参数,只需定义修饰函数以同时接受一个参数:

import functools


def decorate(func):
    @functools.wraps(func)
    def decorated(x):
        func(abs(x))

    return decorated

这将使错误消息更有帮助(而不是在abs调用时引发

或者,如果您只想将abs应用于(比如)第一个参数:

def decorate(func):
    @functools.wraps(func)
    def decorated(x, *args, **kwargs):
        func(abs(x), *args, **kwargs)

    return decorated

您还将注意到^{}。这是一个非常有用的标准库实用程序,用于定义包装函数,例如从装饰程序返回的包装函数。它在包装函数上设置特殊属性,如__name____module__,等等,使其本质上看起来像包装函数

我不确定你的修饰函数在做什么,因为模也在处理负整数,但你基本上有两个问题:

  1. 就像@Anakhand说的,你应该返回一个函数,而不是函数返回值
  2. 您的is_even_new没有返回任何内容

所以我想这是正确的实现方式:

def decorate(func):
    def is_even_new(*args,**kwargs):
        num = abs(*args,**kwargs)
        return func(num)
    return is_even_new

@decorate
def is_even(x):
    if x%2 == 0:
        return True
    else:
        return False

print(is_even(-8))  #  > True

在您的代码中,您需要以正确的方式从decorator返回值,并通过记住其他内部函数的限制(例如,abs take 1 positional参数不多)将输入数据更改为decorator,并且如果不提供值return is_new_even(),您不能直接从外部调用返回函数,如果你想这样做的话,你也需要在那里传递论点

def decorate(func):
    def is_even_new(val):
        num = abs(val)
        return func(num)
    return is_even_new 

@decorate 
def is_even(x):
    if x%2 == 0:
        return True
    else:
        return False

is_even(8)

相关问题 更多 >

    热门问题