использование with – как узнать, какие переменные находятся в контексте

StackOverflow https://stackoverflow.com//questions/12693136

  •  12-12-2019
  •  | 
  •  

Вопрос

В этот код Киви:

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

Видимо Color и d и Ellipse находятся в пространстве имен self.canvas, но откуда Python это знает userdata не находится в том же пространстве имен?

Это было полезно?

Решение

Редактировать:Этот ответ получился немного длинным, поэтому вот краткое изложение:

  1. with self.canvas определяет текущий момент активный холст для следующего блока кода.
  2. Все инструкции по рисованию, такие как Color или Ellipse рисовать на активном холсте.

Пространства имен на самом деле не имеют к этому никакого отношения, важен контекст (см. ниже).

А with оператор позволяет вам использовать так называемый контекстные менеджеры.

Синтаксис такой

with thing [as foo]:

где thing обычно это функция, украшенная contextlib.contextmanager декоратор.Что именно делает контекстный менеджер, зависит от того, как thing реализован.

Но чего он не делает, так это волшебного появления переменной в вашей области видимости.Ссылку на контекст можно получить с помощью необязательного as foo пункт, но это все. Color и Ellipse в вашем примере приходят откуда-то еще (вероятно, импорт?).

Для того, чтобы узнать что именно за контекстный менеджер в with self.canvas линия делает, вам следует посмотреть на Документация по API или исходный код для kivy.graphics.instructions.Canvas.

Вот соответствующий отрывок из руководства:

Используя оператор с ним, все последовательные команды рисования, которые правильно отступают, изменят этот холст.С помощью заявления также гарантировано, что после нашего рисунка внутреннее состояние может быть очищено должным образом.

Итак использовать из Color и Ellipse влияет 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()

Другие советы

На самом деле, Color и Ellipse импортированы из kivy.graphics чуть выше в коде:

from kivy.graphics import Color, Ellipse

Чтобы ответить на ваш вопрос о пространствах имен, Python вообще не нужно «знать», из какого пространства имен он получает переменные.Он имеет очень простые правила пространства имен по сравнению с такими языками, как Java, которые ищут функции, объекты, классы, глобальные области и области пакетов одна за другой.Python имеет одно глобальное пространство имен (для каждого модуля) и стек локальных пространств имен (например,вложенные функции могут получать переменные из внешних функций).Он просто перемещается по списку областей, пока не найдет нужное имя переменной.

А with утверждение выше имеет особое значение, но я думаю, что даже with не может неявно вводить новые переменные в локальную область видимости (одну переменную можно вводить явно с помощью as пункт, однако).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top