在decorator中,如何将正在修饰的函数作为参数传递?

2024-06-28 15:02:18 发布

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

我制作了一个简单的decorator,它基本上将修饰函数放在try...except中。你知道吗

from functools import wraps
def try_except(on_exception=None, exception=Exception, *args, **kwargs):
    from sys import stderr
    def decorator(func):
        @wraps(func)
        def wrapper(*args1, **kwargs1):
            try:
                return func(*args1, **kwargs1)
            except exception as e:
                print(repr(e), file=stderr)
            if on_exception is not None:
                return on_exception(*args, **kwargs)
        return wrapper
    return decorator

然后,我尝试修饰以下函数,因此如果它引发ValueError,它会调用自己:

@try_except(get_int, ValueError, "Please enter a valid integer!\n>>> ")
def get_int(prompt=">>> "):
    return int(input(prompt))

但我得到以下错误:

Traceback (most recent call last):
  File "C:\Python\decorator_test.py", line 9348234, in <module>
    @try_except(get_int, ValueError, "Please enter a valid integer!\n>>> ")
NameError: name 'get_int' is not defined

我知道我可以把它和函数中的try...except放在一个while循环中,但我这样做是为了学习。有什么办法不让这种事发生吗?你知道吗


Tags: 函数fromimportgetreturnondefexception
2条回答

一种方法是定义并使用sentinel对象来表示“call the same修饰的函数正在执行。即,在def try_except前面加上:

same = object()

在包装器的主体中,在try/except之后:

        if on_exception is not None:
            if on_exception is same:
                return decorator(func)(*args, **kwargs)
            else:
                return on_exception(*args, **kwargs)

然后,修饰的函数将是,例如(我假设python3,假设您使用input的方式在python2中无疑是raw_input)…:

@try_except(same, ValueError, "Please enter a valid integer!\n>>> ")
def get_int(prompt=">>> "):
    return int(input(prompt))

解决这个问题的最佳方法是使用一个调用函数的函数。你知道吗

def _get_int(prompt):
    get_int(prompt)
@try_except(_get_int, ValueError, "Please enter a valid integer!\n>>> ")
def get_int(prompt=">>> "):
    return int(input(prompt))
del _get_int

# Or even a lambda

@try_except(lambda p: get_int(p), ValueError, "Please enter a valid integer!\n>>> ")
def get_int(prompt=">>> "):
    return int(input(prompt))

因为_get_int返回调用时get_int返回的内容(即运行时),它将更改为当前的get_int。你知道吗

您可能认为您可以在没有@语法糖的情况下完成它,但这只会调用previous(未修饰)函数,因此它不会递归。你知道吗

相关问题 更多 >