usando with – como saber quais variáveis ​​estão dentro do contexto

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

  •  12-12-2019
  •  | 
  •  

Pergunta

Em este código 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))

Aparentemente Color e d e Ellipse estão dentro do namespace de self.canvas, mas como o Python sabe disso userdata não está dentro do mesmo namespace?

Foi útil?

Solução

Editar:Esta resposta ficou um pouco longa, então aqui está o resumo:

  1. with self.canvas define o momento tela ativa para o seguinte bloco de código.
  2. Todas as instruções de desenho como Color ou Ellipse desenhe na tela ativa.

Namespaces realmente não têm nada a ver com isso, é o contexto que importa (veja abaixo).

O with instrução permite que você use os chamados gerenciadores de contexto.

A sintaxe é assim

with thing [as foo]:

onde thing geralmente é uma função decorada com o contextlib.contextmanager decorador.O que exatamente um gerenciador de contexto faz depende de como thing é implementado.

Mas o que isso não faz é fazer com que a variável apareça magicamente no seu escopo.Uma referência ao contexto pode ser obtida pelo opcional as foo cláusula, mas é isso. Color e Ellipse no seu exemplo vêm de outro lugar (provavelmente importações?).

Para descobrir o que exatamente o gerenciador de contexto no with self.canvas linha faz, você deve olhar para o Documentação da API ou o Código fonte para kivy.graphics.instructions.Canvas.

Aqui está o trecho relevante do tutorial:

Ao usar a instrução com ele, todos os comandos sucessivos de desenho que são corretamente recuados modificarão essa tela.A declaração com com também garante que, após o nosso desenho, o estado interno possa ser limpo corretamente.

Então o usar de Color e Ellipse afeta self.canvas, mas eles não são definidos de forma alguma pela instrução with.

Olhando para o código-fonte, é assim que funciona:

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

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

__enter__ e __exit__ definir o que acontece se um gerenciador de contexto for inserido (antes da primeira linha do código recuado após o with declaração) e saiu.

Neste caso, a tela simplesmente é empurrada para um pilha que define a tela atualmente ativa (e é retirada dela se o gerenciador de contexto for encerrado).

Em kivy.graphics.instructions.Instruction, a classe base aparente para todas as instruções de desenho, a pai está definido para a tela atualmente ativa:

self.parent = getActiveCanvas()

Outras dicas

Na verdade, Color e Ellipse são importados de kivy.graphics um pouco mais alto no código:

from kivy.graphics import Color, Ellipse

Para responder sua pergunta sobre namespaces, o python não precisa "saber" de qual namespace está obtendo variáveis.Possui regras de namespace muito simples em comparação com linguagens como Java, que pesquisam escopos de função, objeto, classe, global e pacote um após o outro.Python tem um namespace global (por módulo) e uma pilha de namespaces locais (por exemplo,funções aninhadas podem obter variáveis ​​de funções externas).Apenas percorre a lista de escopos até encontrar o nome da variável em questão.

O with afirmação acima tem um significado especial, mas acho que mesmo with não pode introduzir implicitamente novas variáveis ​​no escopo local (ele pode introduzir uma variável explicitamente com o as cláusula, no entanto).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top