【问题标题】:Get the name of a decorated function? [duplicate]获取装饰函数的名称? [复制]
【发布时间】:2011-06-20 16:48:41
【问题描述】:

这是我的装饰器:

def check_domain(func):

    def wrapper(domain_id, *args, **kwargs):
        domain = get_object_or_None(Domain, id=domain_id)
        if not domain:
            return None
        return func(domain_id, *args, **kwargs)

    return wrapper

这是一个包装好的函数:

@check_domain
def collect_data(domain_id, from_date, to_date):
    do_stuff(...)

如果我使用collect_data.__name__,我会得到wrapper 而不是collect_data

有什么想法吗?

【问题讨论】:

    标签: python django decorator


    【解决方案1】:

    您可能希望使用来自functools 的wraps。看例子

    >>> from functools import wraps
    >>> def my_decorator(f):
    ...     @wraps(f)
    ...     def wrapper(*args, **kwargs):
    ...         print('Calling decorated function')
    ...         return f(*args, **kwargs)
    ...     return wrapper
    ...
    >>> @my_decorator
    ... def example():
    ...     """Docstring"""
    ...     print('Called example function')
    ...
    >>> example()
    Calling decorated function
    Called example function
    >>> example.__name__
    'example'
    >>> example.__doc__
    'Docstring'
    

    【讨论】:

    • 这是正确答案
    • @Zach Estela 的回答更简单。
    【解决方案2】:

    functools.wraps 是不需要的!只需使用func.__name__

    import time
    
    def timeit(func):
        def timed(*args, **kwargs):
            ts = time.time()
            result = func(*args, **kwargs)
            te = time.time()
            print('Function', func.__name__, 'time:', round((te -ts)*1000,1), 'ms')
            print()
            return result
        return timed
    
    @timeit
    def math_harder():
        [x**(x%17)^x%17 for x in range(1,5555)]
    math_harder()
    
    @timeit
    def sleeper_agent():
        time.sleep(1)
    sleeper_agent()
    

    输出:

    Function math_harder time: 8.4 ms
    Function sleeper_agent time: 1003.7 ms
    

    【讨论】:

    • 在 OP 的情况下,functools.wraps 是不需要的,你是对的 - 不过,在大多数(其他)情况下,使用它仍然是更好的方法。
    • 是的,这个版本在某些情况下不起作用,functools wraps 是正确的选择
    • 我觉得这个不错explained example
    • @ManuelG,你能解释一下在这个解决方案没有的情况下,wraps 是如何工作的吗?据我所知,Zach 的解决方案允许我拥有一个独立的装饰器来完成我需要的工作(即使对于确切的用例 - 即分析代码),所以不要试图偏向这个答案,但如果你有任何计数器例子——我很感兴趣。谢谢!
    • 虽然这个答案暗示了如何从问题中解决问题,但它并没有真正解决问题。在您的代码中,装饰函数名称不固定:sleeper_agent.__name__ == 'timed'。除此之外,functools.wraps 不仅纠正了__name__,它还纠正了例如__doc__。当然要使用functools.wraps,不要重新发明轮子。见stackoverflow.com/questions/308999/what-does-functools-wraps-do
    【解决方案3】:

    对于需要在有多个装饰器时访问装饰函数名称的任何人,如下所示:

    @decorator1
    @decorator2
    @decorator3
    def decorated_func(stuff):
        return stuff
    

    上面提到的functools.wraps 解决了这个问题。

    【讨论】:

      【解决方案4】:

      除了functools.wraps,您还可以查看旨在帮助解决此问题的decorator 模块。

      【讨论】:

        【解决方案5】:

        查看functools.wraps。需要 python 2.5 或更高版本,如果这是一个问题。

        【讨论】:

          【解决方案6】:
          猜你喜欢
          • 1970-01-01
          • 2020-12-18
          • 1970-01-01
          • 2023-01-21
          • 1970-01-01
          • 1970-01-01
          • 2018-10-25
          • 1970-01-01
          • 2012-02-28
          相关资源
          最近更新 更多