我刚刚意识到在 Kivy 中使用添加顶点指令的方式有一些神秘的东西(至少对我来说)with
Python 语句。例如,方式with
使用是这样的:
... some code
class MyWidget(Widget)
... some code
def some_method (self):
with self.canvas:
Rectangle(pos=self.pos, size=self.size)
一开始我以为这只是with
我偶尔使用过的Python语句。但我突然意识到事实并非如此。通常它看起来更像这样(示例取自here):
with open('output.txt', 'w') as f:
f.write('Hi there!')
通常有一个as
在实例之后以及类似对象的别名。在 Kivy 示例中,我们没有定义别名,但这仍然可以。但令我困惑的部分是指令 Rectangle 仍然与 self.canvas 相关联。阅读完有关with
声明中,我非常确信 Kivy 代码应该这样写:
class MyWidget(Widget)
... some code
def some_method (self):
with self.canvas as c:
c.add (Rectangle(pos=self.pos, size=self.size))
我假设在内部该方法add
是被呼叫的人。假设我们可以简单地添加矩形self.add (Rectangle(pos=self.pos, size=self.size))
我是否遗漏了一些关于with
Python 语句?或者这是 Kivy 以某种方式实现的?
我不认识 Kivy,但我想我可以猜出这个具体的构造是如何工作的。
不是保留与您交互的对象(画布?)的句柄,而是with
语句被编程为将其存储在某个对您隐藏的全局变量中。然后,你在里面使用的语句with
使用该全局变量来检索对象。在块的末尾,作为清理的一部分,全局变量被清除。
结果是一个权衡:代码不太明确(这通常是 Python 中所需的功能)。然而,代码更短,这可能会更容易理解(假设读者知道 Kivy 是如何工作的)。这实际上是在 Python 中制作嵌入式 DSL 的技术之一。
其中涉及一些技术细节。例如,如果您希望能够嵌套此类结构(将一个with
在另一个内部),您可能希望使用一个保存此类对象堆栈的全局变量,而不是一个简单的全局变量。另外,如果您需要处理线程,您可以使用线程局部变量而不是全局变量。但通用机制仍然是一样的——Kivy 使用某种保存在你直接控制之外的地方的状态。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)