使用 - 如何知道上下文中的变量

Ter*_*non 0 python kivy

这个Kivy代码中:

class MyPaintWidget(Widget):
    def on_touch_down(self, touch):
        userdata = touch.ud
        with self.canvas:
            Color(1, 1, 0)
            d = 30.
            Ellipse(pos=(touch.x - d/2, touch.y - d/2), size=(d, d))
            userdata['line'] = Line(points=(touch.x, touch.y))
Run Code Online (Sandbox Code Playgroud)

显然Color,d并且Ellipse在命名空间内self.canvas,但Python如何知道userdata不在同一个命名空间内?

Luk*_*raf 5

编辑:这个答案有点冗长,所以这里是摘要:

  1. with self.canvas为以下代码块定义当前活动的画布.
  2. 所有绘图说明喜欢ColorEllipse在活动画布上绘制.

命名空间与它没有任何关系,重要的是上下文(见下文).

with语句允许您使用所谓的上下文管理器.

语法是这样的

with thing [as foo]:
Run Code Online (Sandbox Code Playgroud)

其中,thing通常是装饰与功能contextlib.contextmanager装饰.上下文管理器究竟做了什么取决于如何thing实现.

但它没有做的是让变量神奇地出现在你的范围内.可以通过可选as foo子句获得对上下文的引用,但就是这样.Color并且Ellipse在你的例子是从别的地方来了(可能是进口的?).

为了找出到底是在上下文管理什么with self.canvas行不,你应该看看API文档源代码kivy.graphics.instructions.Canvas.

以下是本教程的相关摘录:

通过对它使用with语句,正确缩进的所有连续绘图命令都将修改此画布.with语句还确保在绘制后,可以正确清理内部状态.

所以使用ColorEllipse影响self.canvas,但他们不以任何方式通过with语句定义.

查看源代码,这是它的工作原理:

def class CanvasBase(InstructionGroup):
    def __enter__(self):
        pushActiveCanvas(self)

    def __exit__(self, *largs):
        popActiveCanvas()
Run Code Online (Sandbox Code Playgroud)

__enter____exit__定义在输入上下文管理器(在with语句之后的第一行缩进代码之前)和退出时会发生什么.

在这种情况下,画布只是被推送到一个堆栈上,该堆栈定义了当前活动的画布(如果退出上下文管理器,则从中弹出).

kivy.graphics.instructions.Instruction所有绘图指令的明显基类中,父项设置为当前活动的画布:

self.parent = getActiveCanvas()
Run Code Online (Sandbox Code Playgroud)