`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 会检查该全局变量以查看它应该在哪里绘制。

【讨论】:

你们俩都给了我一个互补的答案。正如你所说, exitenter 是 here 并且全局变量是 here 但@liori 在他对堆栈的解释中非常准确,这也解决了我的问题一个简单的全局变量的存在的未来问题,他虽然是第一个几秒钟。不过谢谢。 @toto_tico:实际上,我的排在第一位,快了六秒;)然而,Liori 编辑了他的答案并给出了更完整的画面。 老实说,我对知名用户如此快速的回答感到很受宠若惊。特别是在收到 Tumbleweed 徽章后。谢谢。

以上是关于`with canvas:` (Python `with something() as x:`) 如何在 Kivy 中隐式工作?的主要内容,如果未能解决你的问题,请参考以下文章

python3 with open()用法

python常用函数 W

如何在 Python 中使用“with open”打开多个文件?

[Canvas] Introduction to drawing with p5js

Python3 Tkinter基础 Canvas create_rectangle 画一个矩形

html D3:svg,canvas,path,style:SVG Triangle with Outline