Python 查找with:块中定义的函数
以下是来自的一些代码: 我的问题是:他到底是怎么做到的?上下文管理器如何访问with块内的作用域?下面是一个基本模板,用于尝试解决此问题:Python 查找with:块中定义的函数,python,scope,with-statement,contextmanager,Python,Scope,With Statement,Contextmanager,以下是来自的一些代码: 我的问题是:他到底是怎么做到的?上下文管理器如何访问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
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()
编辑:进一步扩展代码,添加一些解释…:
在\uuuu exit\uuuu
处捕获调用方的局部变量很容易——更棘手的是避免那些在with
块之前已经定义的局部变量,这就是为什么我添加到with
应该忽略的两个主要局部函数中。我对这个解决方案不是100%满意,它看起来有点复杂,但我无法用==
或is
进行正确的平等性测试,所以我采用了这个相当复杂的方法
我还添加了一个循环(以更有力地确保
def
s before/in/after得到正确处理)和一个类型检查和函数调用,以确保测试的正确体现是已确定的(一切似乎都正常工作)--当然,编写的代码只有在with
中的def
用于无参数调用的函数时才起作用,因此不难通过inspect
获得签名来避免这种情况(但由于我调用函数只是为了检查是否识别了正确的函数对象,所以我没有考虑最后的优化;-)。回答您的问题,是的,这是框架内省
但是我会创建语法来做同样的事情
with gui.vertical:
text = gui.label('hello!')
items = gui.selection(['one', 'two', 'three'])
@gui.button('click me!')
class button:
def on_click():
text.value = items.value
text.foreground = red
在这里,我将把gui.button
实现为一个装饰器,在给定一些参数和事件的情况下返回按钮实例(尽管现在我觉得button=gui.button('click me!',mybutton\u onclick
也不错)
我也会保留gui.vertical
,因为它可以在没有内省的情况下实现。我不确定它的实现,但它可能涉及设置gui.direction=gui.vertical
,以便gui.label()
和其他人在计算坐标时使用它
现在当我看这个的时候,我想我应该试试语法:
with gui.vertical:
text = gui.label('hello!')
items = gui.selection(['one', 'two', 'three'])
@gui.button('click me!')
def button():
text.value = items.value
foreground = red
(其思想类似于标签是由文本组成的,按钮是由文本和功能组成的)但是为什么要使用“with gui.vertical”?它需要执行相同的堆栈内省来访问其中的文本、项目和按钮。我确信您可以执行类似的操作:class MyLayout(gui.vertical):text=gui.label('hello!')#等等,对吗?不管怎样,我很清楚这是对with block的严重非标准滥用。我只是想知道他是怎么做到的。我希望你至少看到这是对with block的一种很酷的滥用:)我用gui.vertical阅读“不创建元素,但确保在此上下文中创建的所有元素都从当前点垂直计算其坐标”。无需内省。不客气!这是一个有趣的问题,因此,提出它;-)。我发布了一篇博客文章,介绍如何使用您给我的代码,以防您感兴趣:
with gui.vertical:
text = gui.label('hello!')
items = gui.selection(['one', 'two', 'three'])
@gui.button('click me!')
def button():
text.value = items.value
foreground = red