問題描述
我剛剛意識到在 Kivy 中使用 with
Python 語句添加頂點指令的方式有些神秘(至少對我而言).例如,with
的使用方式是這樣的:
I just realized there is something mysterious (at least for me) in the way you can add vertex instructions in Kivy with the with
Python statement. For example, the way with
is used goes something like this:
... some code
class MyWidget(Widget)
... some code
def some_method (self):
with self.canvas:
Rectangle(pos=self.pos, size=self.size)
一開始我以為只是我偶爾使用的with
Python語句.但突然間我意識到事實并非如此.通常它看起來更像這樣(示例取自 這里):
At the beginning I thought that it was just the with
Python statement that I have used occasionally. But suddenly I realize it is not. Usually it looks more like this (example taken from here):
with open('output.txt', 'w') as f:
f.write('Hi there!')
在實例之后通常有一個 as
以及對象的類似和別名.在 Kivy 示例中,我們沒有定義和別名,這仍然可以.但令我困惑的部分是指令 Rectangle 仍然與 self.canvas 相關聯.在閱讀了 with
語句之后,我非常確信 Kivy 代碼應該寫成這樣:
There is usually an as
after the instance and something like and alias to the object. In the Kivy example we don't define and alias which is still ok. But the part that puzzles me is that instruction Rectangle is still associated to the self.canvas. After reading about the with
statement, I am quite convinced that the Kivy code should be written like:
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))
I am assuming that internally the method add
is the one being called. The assumption is based that we can simply add the rectangles with self.add (Rectangle(pos=self.pos, size=self.size))
我是否遺漏了關于 with
Python 語句的某些內容?或者這是 Kivy 實現的某種東西?
Am I missing something about the with
Python statement? or is this somehow something Kivy implements?
推薦答案
我不知道 Kivy,但我想我可以猜到這個具體的構造是如何工作的.
I don't know Kivy, but I think I can guess how this specific construction work.
with
語句不是保留與您正在交互的對象(畫布?)的句柄,而是將其存儲在對您隱藏的某個全局變量中.然后,您在 with
中使用的語句使用該全局變量來檢索對象.在塊的末尾,全局變量作為清理的一部分被清除.
Instead of keeping a handle to the object you are interacting with (the canvas?), the with
statement is programmed to store it in some global variable, hidden to you. Then, the statements you use inside with
use that global variable to retrieve the object. At the end of the block, the global variable is cleared as part of cleanup.
結果是一種權衡:代碼不那么明確(這通常是 Python 中需要的特性).但是,代碼更短,這可能更容易理解(假設讀者知道 Kivy 的工作原理).這實際上是在 Python 中制作嵌入式 DSL 的技術之一.
The result is a trade-off: code is less explicit (which is usually a desired feature in Python). However, the code is shorter, which might lead to easier understanding (with the assumption that the reader knows how Kivy works). This is actually one of the techniques of making embedded DSLs in Python.
涉及一些技術細節.例如,如果您希望能夠嵌套這樣的結構(將一個 with
放在另一個中),而不是一個簡單的全局變量,您可能希望使用一個全局變量來保存這些對象的堆棧.此外,如果您需要處理線程,您將使用線程局部變量而不是全局變量.但是通用機制仍然是相同的——Kivy 使用了一些保存在你無法直接控制的地方的狀態.
There are some technicalities involved. For example, if you want to be able to nest such constructions (put one with
inside another), instead of a simple global variable you would want to use a global variable that keeps a stack of such objects. Also, if you need to deal with threading, you would use a thread-local variable instead of a global one. But the generic mechanism is still the same—Kivy uses some state which is kept in a place outside your direct control.
這篇關于`with canvas:` (Python `with something() as x:`) 如何在 Kivy 中隱式工作?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!