`with canvas:`(Python`with something()as x:`)如何隐式地在Kivy中工作?

tot*_*ico 6 python kivy

我只是意识到在使用withPython语句在Kivy中添加顶点指令的方式中有一些神秘的东西(至少对我而言).例如,使用的方式with是这样的:

... some code
class MyWidget(Widget)
    ... some code 

    def some_method (self):
        with self.canvas:
           Rectangle(pos=self.pos, size=self.size)
Run Code Online (Sandbox Code Playgroud)

一开始我认为这只是with偶尔使用的Python语句.但我突然意识到事实并非如此.通常它看起来更像这样(从这里取的例子):

with open('output.txt', 'w') as f:
   f.write('Hi there!')
Run Code Online (Sandbox Code Playgroud)

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))
Run Code Online (Sandbox Code Playgroud)

我假设在内部方法add是被调用的方法.假设我们可以简单地添加矩形self.add (Rectangle(pos=self.pos, size=self.size))

我错过了关于withPython语句的一些内容吗?或者这是Kivy实施的某种方式?

lio*_*ori 5

我不知道Kivy,但我想我能猜出这个具体的建筑是如何工作的.

而不是保持与您正在交互的对象(画布?)的句柄,该with语句被编程为将其存储在一些隐藏给您的全局变量中.然后,您在内部with使用的语句使用该全局变量来检索该对象.在块结束时,全局变量将作为清理的一部分被清除.

结果是权衡:代码不那么明确(这通常是Python中所需的特性).但是,代码更短,这可能会导致更容易理解(假设读者知道Kivy如何工作).这实际上是用Python制作嵌入式DSL的技术之一.

涉及一些技术细节.例如,如果您希望能够嵌套此类构造(将一个构造放在with另一个构造中),而不是简单的全局变量,则需要使用保留此类对象堆栈的全局变量.此外,如果您需要处理线程,则可以使用线程局部变量而不是全局变量.但是通用机制仍然是相同的 - 基维使用了一些保存在你直接控制范围之外的状态.