简体   繁体   English

此python装饰器的一种更优雅的方式

[英]A more elegant way for this python decorator

Basically I want a decorator with an argument list that contains more than just a function to be able to be called from both the @- and regular forms. 基本上,我希望装饰器具有一个参数列表,该参数列表不仅包含一个函数,而且可以从@-和常规形式中进行调用。 I've "designed" a quick workaround, but it's ugly and executes a function in @-form immediately, which is an undesired side-effect (that's due to return body_two() of course). 我已经“设计”了一个快速的解决方法,但是它很丑陋,并立即以@ -form形式执行一个函数,这是不希望的副作用(这当然是由于返回body_two()所致)。

def status_display_with_comment(comment, closure = None):
    def body_one(function = None):
        def body_two():
            print(comment)
            #an ugly workaround to be able to run both the @- and regular forms
            if function != None:
                print("Entering", function.__name__)
                function()
                print("Exited", function.__name__)
            elif closure != None:
                print("Entering", closure.__name__)
                closure()
                print("Exited", closure.__name__)
        return body_two()
    return body_one

def a_function():
    print('a_function executes')

@status_display_with_comment(comment = 'some comment')
def a_function_with_comment():
   print('a_function_with_comment executes')

a_function_status_display_with_comment = status_display_with_comment(closure = a_function, comment = 'a comment')

a_function_status_display_with_comment()

Thanks in advance. 提前致谢。

PS: I have to wrap my head around that whole closure thing. PS:我必须把头放在整个封闭的东西上。 Which is fun considering it could be done recursively like in Scheme (a long time ago for me). 考虑到可以像在Scheme中那样递归完成(很久以前对我来说),这很有趣。

You want a function that returns a decorator: 您需要一个返回装饰器的函数:

def status_display_with_comment(comment):
    def decorator(function):
        def wrapper():
            print(comment)
            print("Entering", function.__name__)
            result = function()
            print("Exited", function.__name__)
            return result
        return wrapper

    return decorator


def a_function():
    print('a_function executes')



a_function_SD_WC = status_display_with_comment('a comment')(a_function)
a_function_SD_WC()

Also works: 也可以:

@status_display_with_comment('a comment')
def a_function():
    print('a_function executes')


a_function()

The regular, direct decorator already returns a closure: 常规的直接装饰器已经返回了一个闭包:

def a_normal_decorator(function):
    def wrapper():
        return function()
    return wrapper

wrapper here is a closure since it has to keep function around even after a_normal_decorator finished executing. wrapper是一个闭包,因为即使a_normal_decorator完成执行后,它也必须保持function


For reference, this is how an idiomatic decorator is usually written: 供参考,这是惯用修饰符通常的编写方式:

import functools

def decorator(function):
    @functools.wraps(function)
    def wrapper(*a, **kw):
        return function(*a, **kw)

    return wrapper

That is, it passes arguments to the wrapped function and doesn't throw away its return value. 也就是说,它将参数传递给包装的函数,并且不会丢弃其返回值。

functools.wraps copies from the function being wrapped to the wrapper function __name__ , __module__ , __annotations__ and __doc__ , the documentation string. functools.wraps从函数副本被包装到包装函数__name____module____annotations____doc__ ,文档字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM