装饰函数有没有办法引用装饰器创建的对象?

Tan*_*guy 5 python python-decorators

我想知道装饰函数是否有办法引用装饰器包装器创建的对象.当我想要使用装饰器时,我的问题出现了:

  1. 制作一个用子图创建图形的包装器
  2. 在包装器内执行装饰函数,这将添加一些图
  3. 最后将数字保存在包装器中

但是,修饰函数需要引用包装器创建的图形.装饰函数如何引用该对象?我们是否必须诉诸全局变量?

这是一个简短的例子,我在装饰函数中引用了一个在包装器中创建的变量(但是我没有设法在没有使用全局变量的情况下执行此操作):

def my_decorator(func):
    def my_decorator_wrapper(*args, **kwargs):
        global x
        x = 0
        print("x in wrapper:", x)
        return func(*args, **kwargs)
    return my_decorator_wrapper

@my_decorator
def decorated_func():
    global x
    x += 1
    print("x in decorated_func:", x)

decorated_func()
# prints:
# x in wrapper: 0
# x in decorated_func: 1
Run Code Online (Sandbox Code Playgroud)

我知道这很容易在课堂上完成,但我出于好奇而问这个问题.

JL *_*ret 1

是的,函数可以通过查看自身来引用它。

装饰器端。它只需要属性并将它们设置在函数上

如果它看起来有点复杂,那是因为接受参数的装饰器需要这个特定的结构才能工作。看到带参数的装饰器吗?

def declare_view(**kwds):
    """declaratively assocatiate a Django View function with resources
    """

    def actual_decorator(func):
        for k, v in kwds.items():
            setattr(func, k, v)

        return func

    return actual_decorator
Run Code Online (Sandbox Code Playgroud)

调用装饰器

@declare_view(
    x=2
)
def decorated_func():
    #the function can look at its own name, because the function exists 
    #by the time it gets called.
    print("x in decorated_func:", decorated_func.x)

decorated_func()
Run Code Online (Sandbox Code Playgroud)

输出

x in decorated_func: 2 
Run Code Online (Sandbox Code Playgroud)

在实践中我已经用过很多次了。我的想法是将 Django 视图函数与它们必须协作的特定后端数据类和模板相关联。因为它是声明性的,所以我可以内省所有 Django 视图并跟踪它们关联的 URL 以及自定义数据对象和模板。工作得很好,但是,是的,该函数确实期望某些属性存在于其自身上。它不知道装饰者设置了它们。

哦,就我而言,没有充分的理由让这些变量在我的用例中作为参数传递,这些变量基本上保存着从函数的 POV 来看永远不会改变的硬编码值。

起初很奇怪,但非常强大,并且没有运行时或维护方面的缺点。

这是一些将其置于上下文中的实例。

@declare_view(
    viewmanager_cls=backend.VueManagerDetailPSCLASSDEFN,
    template_name="pssecurity/detail.html",
    objecttype=constants.OBJECTTYPE_PERMISSION_LIST[0],
    bundle_name="pssecurity/detail.psclassdefn",
)
def psclassdefn_detail(request, CLASSID, dbr=None, PORTAL_NAME="EMPLOYEE"):
    """

    """
    f_view = psclassdefn_detail
    viewmanager = f_view.viewmanager_cls(request, mdb, f_view=f_view)
    ...do things based on the parameters...
    return viewmanager.HttpResponse(f_view.template_name)
Run Code Online (Sandbox Code Playgroud)

  • 你可以设置函数的属性!? (2认同)
  • 在 Python 中,一切都是对象。所以,是的,由于视图是 Python 对象并且没有 __slots__`,因此您可以在它们上设置任意属性。在 Python 2 和 3 之间,它们自己的内部属性发生了一些变化。例如,3 中的名称可能是 `func.__name__`,但 2 中的名称可能稍微复杂一些。 (2认同)