查找 with: 块中定义的函数
以下是 Richard Jones 博客 中的一些代码:
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
Here's some code from 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
My question is: how the heck did he do this? How can the context manager access the scope inside the with block? Here's a basic template for trying to figure this out:
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
回答你的问题,是的,这就是框架内省。
但是我要创建做同样事情的语法是
这里我将实现
gui.button
作为一个装饰器,它返回给定一些参数和事件的按钮实例(尽管现在在我看来button = gui.button('click me!', mybutton_onclick 也可以)。
我也会保留 gui.vertical ,因为它可以在不自省的情况下实现。不确定它的实现,但它可能涉及设置 gui.direction = gui.VERTICAL 以便 gui.label() 和其他人在计算坐标
时 使用它。我看看这个,我想我会尝试一下语法:(
这个想法类似于标签是如何由文本制成的,按钮是由文本和功能制成的)
To answer your question, yes, it's frame introspection.
But the syntax I would create to do the same thing is
Here I would implement
gui.button
as a decorator that returns button instance given some parameters and events (though it appears to me now thatbutton = gui.button('click me!', mybutton_onclick
is fine as well).I would also leave
gui.vertical
as it is since it can be implemented without introspection. I'm not sure about its implementation, but it may involve settinggui.direction = gui.VERTICAL
so thatgui.label()
and others use it in computing their coordinates.Now when I look at this, I think I'd try the syntax:
(the idea being that similarly to how label is made out of text, a button is made out of text and function)
这是一种方法:
编辑:进一步拉伸代码,添加一些解释...:
在
__exit__
处捕获调用者的本地变量很容易 - 更棘手的是避免那些已经存在的本地变量定义在with
块之前,这就是为什么我在 main 中添加了with
应该忽略的两个本地函数。 我对这个解决方案并不是 100% 满意,它看起来有点复杂,但我无法使用==
或is
进行正确的相等测试,所以我求助于对于这种相当复杂的方法。我还添加了一个循环(以更加有力地确保正确处理之前/之内/之后的
def
)和类型检查和函数调用,以确保def 的正确体现code>testing
是已识别的(一切似乎都工作正常)——当然,只有当with
内的def
为对于不带参数的可调用函数,使用inspect
获取签名来防止这种情况并不难(但由于我进行调用只是为了检查是否识别了正确的函数对象,我没有关心这最后的改进;-)。Here's one way:
Edit: stretched code a bit more, added some explanation...:
Catching caller's locals at
__exit__
is easy -- trickier is avoiding those locals that were already defined before thewith
block, which is why I added to main two local functions that thewith
should ignore. I'm not 100% happy with this solution, which looks a bit complicated, but I couldn't get equality testing correct with either==
oris
, so I resorted to this rather complicated approach.I've also added a loop (to make more strongly sure the
def
s before / within / after are being properly handled) and a type-check and function-call to make sure the right incarnation oftesting
is the one that's identified (everything seems to work fine) -- of course the code as written only works if thedef
inside thewith
is for a function callable without arguments, it's not hard to get the signature withinspect
to ward against that (but since I'm doing the call only for the purpose of checking that the right function objects are identified, I didn't bother about this last refinement;-).