这是Richard Jones' Blog的一些代码:
with gui.vertical:
text = gui.label('hello!')
items = gui.selection(['one', 'two', 'three'])
with gui.button('click me!'):
def on_click():
text.value = items.value
text.foreground = red
我的问题是:他到底是怎么做到的?上下文管理器如何访问with块内的范围?这是一个试图弄清楚这一点的基本模板:
from __future__ import with_statement
class button(object):
def __enter__(self):
#do some setup
pass
def __exit__(self, exc_type, exc_value, traceback):
#XXX: how can we find the testing() function?
pass
with button():
def testing():
pass
最佳答案
这是一种方法:
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
中添加了两个主要的本地函数的原因。我对这个解决方案不太满意,该解决方案看起来有点复杂,但是我无法使用==
或is
正确进行相等性测试,因此我采用了这种相当复杂的方法。我还添加了一个循环(以确保在正确地处理之前/之内/之后的
def
)和一个类型检查和函数调用,以确保testing
的正确化身已被识别(所有内容)似乎工作正常)-当然,仅当def
中的with
用于无需参数即可调用的函数时,编写的代码才有效,因此不难获得带有inspect
的签名以对抗该问题(但是由于我正在调用仅是为了检查是否标识了正确的函数对象,我对最后的改进并不感到烦恼;-)。关于python - 查找用: Block定义的函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1255914/