首页 > 解决方案 > Wrapper/decorator - 获取它执行的方法的变量的值

问题描述

在包装器/装饰器中,是否有可能在它执行的方法中获取变量的值?

在这个例子中,我想直接在包装器中打印变量helloThere的内容。

实际上,我需要直接从包装器中根据这个变量执行一些其他命令(在另一个类中)。

from functools import wraps

class myclass:
    def __init__(self):
        pass

    def _wrapped(f):
        @wraps(f)
        def wrapper(self, *args, **kwargs):
            print(helloThere)
        return wrapper

    @_wrapped
    def doA(self):
        helloThere = "Obi-Wan Kenobi"

    @_wrapped
    def doB(self):
        helloThere = "General Grievous"

先感谢您!

标签: python-3.xvariableswrapper

解决方案


神圣的黑客,这没有优化,可能有十亿种出错的地方,但它显示了 Python 是多么的神奇。

如果那里有更优雅的东西,我会很感兴趣。

(如果您选择使用它,您的任务是融入装饰器。)

from dill.source import getsourcelines

# Some arbitrary method, that the decorator would wrap.
def print_hi():
    var = 1
    var2 = 2
    return var2

# converts the print_hi method into lines of code
lines = getsourcelines(print_hi)[0]

# rebuild, yielding the variable you want after it is defines. 
# you would need to add some complexity to search for the variable
# definition
new_lines = [lines[0], lines[1], "    yield var\n", lines[2], lines[3]]

# Re - hydrate into code
f = ''.join(new_lines)

# Make the function return statement a yield statement, so you 
# can get at it. 
f = f.replace("return", "yield")

# re-define the method. Note, you would probably want to replace 
# the method name as well so you don't monkey patch it everywhere
# it is used. 
exec(f)

# In your decorator, you can now for-loop on the function, since you
# converted it to yield instead of return.
for i in print_hi():
    print(i)

同样,这只是一个概念证明。让它变得健壮需要做很多工作——但它是可以做到的。


推荐阅读