`with canvas:` (Python `with something() as x:`) 如何在 Kivy 中隐式工作?
Posted
技术标签:
【中文标题】`with canvas:` (Python `with something() as x:`) 如何在 Kivy 中隐式工作?【英文标题】:how does `with canvas:` (Python `with something() as x:`) works implicitly in Kivy? 【发布时间】:2013-06-19 21:28:31 【问题描述】:我刚刚意识到在 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 实现的某种东西?
【问题讨论】:
【参考方案1】:我不认识 Kivy,但我想我可以猜到这个特定的构造是如何工作的。
with
语句不是保留与您交互的对象(画布?)的句柄,而是将其存储在某个全局变量中,对您隐藏。然后,您在 with
中使用的语句使用该全局变量来检索对象。在块的末尾,全局变量作为清理的一部分被清除。
结果是一种权衡:代码不那么明确(这通常是 Python 中需要的特性)。但是,代码更短,这可能会更容易理解(假设读者知道 Kivy 的工作原理)。这实际上是在 Python 中制作嵌入式 DSL 的技术之一。
涉及一些技术细节。例如,如果您希望能够嵌套这样的结构(将一个 with
放在另一个内部),而不是一个简单的全局变量,您可能希望使用一个全局变量来保存这些对象的堆栈。此外,如果您需要处理线程,您将使用线程局部变量而不是全局变量。但是通用机制仍然是相同的——Kivy 使用了一些保存在你无法直接控制的地方的状态。
【讨论】:
您非常准确地指出a stack 的存在,当我在某处考虑全局变量时,它解决了我的问题。谢谢你!【参考方案2】:with
语句没有任何额外神奇之处,但也许您不知道它是如何工作的?
为了在with
语句中使用任何对象,它必须实现两个方法:__enter__
和__exit__
。 __enter__
在进入 with
块时调用,__exit__
在退出块时调用出于任何原因。
对象在其__enter__
方法中的作用当然取决于它。由于我没有 Kivy 代码,我只能猜测它的 canvas.__enter__
方法在某处设置了一个全局变量,而 Rectangle
会检查该全局变量以查看它应该在哪里绘制。
【讨论】:
你们俩都给了我一个互补的答案。正如你所说, exit 和 enter 是 here 并且全局变量是 here 但@liori 在他对堆栈的解释中非常准确,这也解决了我的问题一个简单的全局变量的存在的未来问题,他虽然是第一个几秒钟。不过谢谢。 @toto_tico:实际上,我的排在第一位,快了六秒;)然而,Liori 编辑了他的答案并给出了更完整的画面。 老实说,我对知名用户如此快速的回答感到很受宠若惊。特别是在收到 Tumbleweed 徽章后。谢谢。以上是关于`with canvas:` (Python `with something() as x:`) 如何在 Kivy 中隐式工作?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Python 中使用“with open”打开多个文件?
[Canvas] Introduction to drawing with p5js