<p>非常有趣的问题。要实现这一点,您需要深入研究函数对象(不管怎样,都不要使用<code>eval</code>、<code>exec</code>或<code>ast</code>之类的东西)。你知道吗</p>
<pre><code>def create_closure(objs):
creat_cell = lambda x: (lambda: x).__closure__[0]
return tuple(create_cell(obj) for obj in objs)
</code></pre>
<p/><p/>
<pre><code>def hijack(mapper):
from types import FunctionType
def decorator(f):
globals_ = {k: mapper(v) for k, v in f.__globals__.items()}
closure_ = f.__closure__
if closure_:
closure_ = create_closure(i.cell_contents for i in closure_)
return (lambda *arg, **kwarg:
FunctionType(f.__code__, globals_, f.__name__,
f.__defaults__, closure_)(*arg, **kwarg))
return decorator
</code></pre>
<p>测试:</p>
<pre><code>x = 'x'
y = 'y'
@hijack(lambda obj: 'hijacked!' if obj is x else obj)
def f():
return (x, y)
f()
</code></pre>
<p>输出:</p>
<pre><code>('hijacked!', 'y')
</code></pre>
<p>最终解决了原来的问题:</p>
<pre><code>x = lambda: 'x()'
y = lambda: 'y()'
mydecorator = lambda f: lambda *arg, **kwarg: f(*arg, **kwarg) + ' decorated!'
targets = {id(x): mydecorator(x)}
def mapper(obj):
if id(obj) in targets:
return targets[id(obj)]
else:
return obj
@hijack(mapper)
def f():
return (x(), y())
f()
</code></pre>
<p>输出:</p>
<pre><code>('x() decorated!', 'y()')
</code></pre>