猿问

Python 3.5 装饰器和函数字段

我有以下代码片段:


def wrapper(func):

    def wrapped(*args, **kwargs):

        func.var = 0

        return func(*args, **kwargs)

    return wrapped


@wrapper

def f_out():

    print(f_out.var)

你能解释一下为什么跑步f_out()会加薪吗:


AttributeError: 'function' object has no attribute 'var'

编辑


我不得不详细说明,因为答案给了我替代方案,但这不适用于我想要的情况。鉴于以下代码段:


def wrapper(func):

    def wrapped(*args, **kwargs):

        func.var = 0

        ret = func(*args, **kwargs)

        print(func.var)

    return wrapped


@wrapper

def f_out():

    f_out.var = 1

f_out()

print(f_out.var)

我得到作为输出:


0

1

为什么会这样?


开心每一天1111
浏览 144回答 3
3回答

一只名叫tom的猫

正确的方法是返回包装的函数并在返回之前更改它:def wrapper(func):    def wrapped(*args, **kwargs):        return func(*args, **kwargs)    wrapped.var = 0    return wrapped@wrapperdef f_out():    print(f_out.var)你正确地得到:print(f_out())给0更新的剪辑更改了var属性两次:第一次在包装器中将原始函数的属性设置为 0 并在调用原始函数后打印它然后,当从包装器调用原始函数时,它将引用 as 的函数f_out的属性设置为1。但在那一刻,引用 as 的函数f_out是被封装的函数,不再是原始函数。因此,当您稍后打印时,f_out.var您将打印包装函数的属性,即 1。这是一个稍微修改的代码来演示它:def wrapper(func):    def wrapped(*args, **kwargs):        wrapped.orig = func          # keeps a ref to the original function        func.var = 0        ret = func(*args, **kwargs)        print(func.var)    return wrapped@wrapperdef f_out():    f_out.var = 1f_out()print(f_out.var, f_out.orig.var)它打印01 0

青春有我

当您调用它时,装饰器正在包装您的函数。因此,当您调用f_out()它时,它会返回1. 您调用的是包装函数,而不是定义。@wrapperdef f_out()wrapper(f_out)当你调用它时相等 。当您尝试打印时,f_out.var它会返回函数定义中的值。

小唯快跑啊

return wrapped如果return func试试这个,你必须添加:def wrapper(func):    def wrapped(*args, **kwargs):        func.var = 0        return func(*args, **kwargs)    return wrapped@wrapperdef f_out():    print(f_out.var)
随时随地看视频慕课网APP

相关分类

Python
我要回答