Question

Dans ce code 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))

Apparemment Color et d et Ellipse sont dans l'espace de noms de self.canvas, mais comment Python sait-il cela userdata n'est pas dans le même espace de noms ?

Était-ce utile?

La solution

Modifier:Cette réponse est un peu longue, voici donc le résumé :

  1. with self.canvas définit l'actuel toile active pour le bloc de code suivant.
  2. Toutes les instructions de dessin comme Color ou Ellipse dessiner sur le canevas actif.

Les espaces de noms n'ont pas vraiment quelque chose à voir là-dedans, c'est le contexte qui compte (voir ci-dessous).

Le with L'instruction vous permet d'utiliser ce qu'on appelle gestionnaires de contexte.

La syntaxe est comme ça

with thing [as foo]:

thing est généralement une fonction décorée du contextlib.contextmanager décorateur.Ce que fait exactement un gestionnaire de contexte dépend de la façon dont thing est implémenté.

Mais ce qu'il ne fait pas, c'est faire apparaître comme par magie la variable dans votre champ d'application.Une référence au contexte peut être obtenue par l'option facultative as foo clause, mais c'est tout. Color et Ellipse dans votre exemple, ils viennent d'ailleurs (probablement des importations ?).

Afin de savoir ce qu'est exactement le gestionnaire de contexte dans le with self.canvas la ligne le fait, vous devriez regarder le Documentation API ou la code source pour kivy.graphics.instructions.Canvas.

Voici l'extrait pertinent du tutoriel :

En utilisant l'instruction avec lui, toutes les commandes de dessin successives qui sont correctement en retrait modifieront cette toile.La déclaration avec assure également qu'après notre dessin, l'état interne peut être nettoyé correctement.

Alors le utiliser de Color et Ellipse affecte self.canvas, mais ils ne sont en aucun cas définis par l'instruction with.

En regardant le code source, voici comment cela fonctionne :

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

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

__enter__ et __exit__ définir ce qui se passe si un gestionnaire de contexte est entré (avant la première ligne de code en retrait après le with déclaration) et quitté.

Dans ce cas, la toile est simplement poussée sur un empiler qui définit le canevas actuellement actif (et en est extrait si le gestionnaire de contexte est quitté).

Dans kivy.graphics.instructions.Instruction, la classe de base apparente pour toutes les instructions de dessin, la le parent est défini sur le canevas actuellement actif:

self.parent = getActiveCanvas()

Autres conseils

En fait, Color et Ellipse sont importés de kivy.graphics un peu plus haut dans le code :

from kivy.graphics import Color, Ellipse

Pour répondre à votre question sur les espaces de noms, python n'a pas du tout besoin de "savoir" de quel espace de noms il obtient les variables.Il a des règles d'espace de noms très simples par rapport à des langages comme Java, qui recherchent les étendues de fonction, d'objet, de classe, globales et de package les unes après les autres.Python a un espace de noms global (par module) et une pile d'espaces de noms locaux (par ex.les fonctions imbriquées peuvent accéder aux variables des fonctions externes).Il parcourt simplement la liste des étendues jusqu'à ce qu'il trouve le nom de la variable en question.

Le with la déclaration ci-dessus a une signification particulière, mais je pense que même with ne peut pas introduire implicitement de nouvelles variables dans la portée locale (il peut introduire explicitement une variable avec le as clause, cependant).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top