簡體   English   中英

在裝飾器中,如何傳遞要裝飾的函數作為參數?

[英]In a decorator how can I pass the function I'm decorating as an argument?

我做了這個簡單的裝飾器,基本上將裝飾的功能放在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循環中,但函數中try...except ,但這是我的一項學習練習。 有什么辦法可以避免這種情況的發生?

修復此問題的最佳方法是使用調用該函數的函數。

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目前。

您可能認為您可以在沒有@語法糖的情況下完成此操作,但這只會調用先前的(未裝飾的)函數,因此不會遞歸。

一種方法是定義並使用哨兵對象表示“調用正在執行的相同修飾函數。即,在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)

然后,裝飾的函數將是(例如,Python 3,我想,考慮到您使用input的方式-無疑在Python 2中將是raw_input )...:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM