Python-装饰器

2024-05-17 13:11:33 发布

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

我在努力学习Decorators。 我理解它的概念,现在正努力实现它。

这是我编写的代码 代码是不言而喻的。它只检查是否传入了参数int

def wrapper(func):
    def inner():
        if issubclass(x,int): pass
        else: return 'invalid values'

    return inner()

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

print add('a',2)

global name 'x' is not defined是抛出错误。我知道它不是在inner下定义的,但不知道如何更正此代码?我哪里做错了?


Tags: 代码decoratorsadd概念参数returnifdef
3条回答

我发现你当前的代码有三个问题。

首先,调用inner函数,而不是返回对它的引用。

其次,您的inner函数的参数与您要装饰的函数的参数不同。在这种情况下,您至少需要显式地接受x参数(一些内部函数可以独占地使用*args**kwargs,但不一定是您的函数)。

最后,您永远不会调用包装函数。虽然这不是严格要求的(在开发过程中用decorator替换方法可能很有用),但通常您希望在内部函数的代码中的某个时刻调用该函数。

所以,为了把整个事情都总结起来,我想你希望你的代码是这样的:

def wrapper(func):
    def inner(x, y):
        if issubclass(x, int): # issue 2
            return func(x, y) # issue 3
        else:
            return "invalid values" # consider raising an exception here instead!

    return inner # issue 1

如果要在类型检查失败时正确终止add方法,也可以引发异常。像这样

def check_int_types(func):
    def type_checker(x, y):
        if issubclass(type(x), int) and issubclass(type(y), int):
            return func(x, y)
        raise Exception("Invalid types: {}, {}".format(x, y))
    return type_checker

@check_int_types
def add(a, b):
    return a + b

def main():
    x = y = 15.0
    print add(x, y)

if __name__ == '__main__':
    main()

结果:

Traceback (most recent call last):
  File "deco_test.py", line 17, in <module>
    main()
  File "deco_test.py", line 14, in main
    print add(x, y)
  File "deco_test.py", line 5, in type_checker
    raise Exception("Invalid types: {}, {}".format(x, y))
Exception: Invalid types: 15.0, 15.0

你的装潢师应该看起来像:

def wrapper(func):
    def inner(x, y): # inner function needs parameters
        if issubclass(type(x), int): # maybe you looked for isinstance?
            return func(x, y) # call the wrapped function
        else: 
            return 'invalid values'
    return inner # return the inner function (don't call it)

一些要点:

  • issubclass需要一个类作为第一个参数(您可以用一个简单的try/except TypeError替换它)。
  • 包装器应该返回一个函数,而不是被调用函数的结果
  • 实际上应该在内部函数中调用包装函数
  • 你的内在功能没有参数

你可以找到一个很好的解释。

相关问题 更多 >