这个基维代码:

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))

显然 ColordEllipse 位于命名空间内 self.canvas, ,但是Python怎么知道这一点 userdata 不在同一个命名空间内?

有帮助吗?

解决方案

编辑:这个答案有点长,所以总结如下:

  1. with self.canvas 定义当前 活动画布 对于以下代码块。
  2. 所有绘图说明如 Color 或者 Ellipse 在活动画布上绘制。

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

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

语法是这样的

with thing [as foo]:

在哪里 thing 通常是一个用 contextlib.contextmanager 装饰师。上下文管理器到底做什么取决于如何 thing 已实施。

但它并没有让变量神奇地出现在你的作用域中。对上下文的引用可以通过可选的 as foo 条款,但仅此而已。 ColorEllipse 在你的例子中来自其他地方(可能是进口?)。

为了找出上下文管理器到底是什么 with self.canvas 线确实如此,你应该看看 API文档 或者 源代码 为了 kivy.graphics.instructions.Canvas.

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

通过使用Want with语句,所有连续缩进的连续绘图命令都会修改该画布。带有陈述还可以确保在我们的绘画之后,可以正确清理内部状态。

所以 使用ColorEllipse 影响 self.canvas, ,但它们不以任何方式由 with 语句定义。

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

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

    def __exit__(self, *largs):
        popActiveCanvas()

__enter____exit__ 定义如果输入上下文管理器(在缩进代码的第一行之前)会发生什么 with 声明)并退出。

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

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

self.parent = getActiveCanvas()

其他提示

实际上, ColorEllipse 是从进口的 kivy.graphics 代码稍高一点:

from kivy.graphics import Color, Ellipse

要回答有关命名空间的问题,Python 根本不需要“知道”它从哪个命名空间获取变量。与 Java 等语言相比,它的命名空间规则非常简单,Java 会依次搜索函数、对象、类、全局和包范围。Python 有一个全局命名空间(每个模块)和一堆本地命名空间(例如嵌套函数可以从外部函数获取变量)。它只是沿着范围列表向下查找,直到找到有问题的变量名称。

with 上面的说法有特殊含义,但我认为即使 with 不能隐式地将新变量引入局部作用域(它可以使用 as 不过,条款)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top