这是一种方法:
from __future__ import with_statement
import inspect
class button(object):
def __enter__(self):
# keep track of all that's already defined BEFORE the `with`
f = inspect.currentframe(1)
self.mustignore = dict(f.f_locals)
def __exit__(self, exc_type, exc_value, traceback):
f = inspect.currentframe(1)
# see what's been bound anew in the body of the `with`
interesting = dict()
for n in f.f_locals:
newf = f.f_locals[n]
if n not in self.mustignore:
interesting[n] = newf
continue
anf = self.mustignore[n]
if id(newf) != id(anf):
interesting[n] = newf
if interesting:
print 'interesting new things: %s' % ', '.join(sorted(interesting))
for n, v in interesting.items():
if isinstance(v, type(lambda:None)):
print 'function %r' % n
print v()
else:
print 'nothing interesting'
def main():
for i in (1, 2):
def ignorebefore():
pass
with button():
def testing(i=i):
return i
def ignoreafter():
pass
main()
编辑:更多的延伸代码,添加了一些解释......:
捕捉调用者的本地人__exit__
很容易——更棘手的是避免那些在块之前已经定义的本地人,这就是为什么我添加了两个应该忽略with
的主要本地函数。with
我对这个解决方案不是 100% 满意,它看起来有点复杂,但是我无法用==
or得到正确的相等性测试is
,所以我采用了这种相当复杂的方法。
我还添加了一个循环(以更强烈地确保def
正确处理之前/内部/之后的 s)和一个类型检查和函数调用,以确保正确的化身testing
是被识别的那个(一切似乎工作正常)——当然,编写的代码只有在def
内部用于不带参数的可调用函数时才有效,因此获得签名以防止这种with
情况并不难(但因为我只是为了目的而进行调用inspect
检查是否识别了正确的函数对象,我没有为最后的改进而烦恼;-)。