tag - Wie kann man wissen, welche Variablen im Kontext stehen
Frage
In dieser Kivy-Code:
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))
Offenbar Color
und d
und Ellipse
befinden sich im Namensraum von self.canvas
, aber woher weiß Python das userdata
befindet sich nicht im selben Namensraum?
Lösung
Bearbeiten:Diese Antwort wurde etwas langwierig, also hier ist die Zusammenfassung:
with self.canvas
definiert die aktuell aktive Leinwand für den folgenden Codeblock.- Alle Zeichenanweisungen wie
Color
oderEllipse
zeichnen Sie auf der aktiven Leinwand.
Namespaces haben eigentlich nichts damit zu tun, es kommt auf den Kontext an (siehe unten).
Der with
anweisung ermöglicht es Ihnen, sogenannte zu verwenden kontextmanager.
Die Syntax ist wie folgt
with thing [as foo]:
wo thing
normalerweise ist eine Funktion mit dem verziert contextlib.contextmanager
Dekorator.Was genau ein Kontextmanager tut, hängt davon ab, wie thing
implementiert ist.
Aber was es nicht tut, ist, Variable magisch in Ihrem Bereich erscheinen zu lassen.Ein Verweis auf den Kontext kann durch das Optionale erhalten werden as foo
klausel, aber das war's. Color
und Ellipse
in Ihrem Beispiel kommen von woanders (wahrscheinlich Importe?).
Um herauszufinden, was genau der Kontextmanager in der with self.canvas
linie tut, sollten Sie sich das ansehen API-Dokumentation oder die Quellcode für kivy.graphics.instructions.Canvas
.
Hier ist der relevante Auszug aus dem Tutorial:
Durch die Verwendung der with-Anweisung damit werden alle aufeinanderfolgenden Zeichenbefehle richtig eingerückte Elemente ändern diese Zeichenfläche.Die mit Aussage stellt auch sicher, dass nach unserer Zeichnung der interne Zustand gereinigt werden kann richtig hoch.
Also das verwenden von Color
und Ellipse
beeinflussen self.canvas
, aber sie werden in keiner Weise durch die with Anweisung definiert.
Wenn Sie sich den Quellcode ansehen, funktioniert das so:
def class CanvasBase(InstructionGroup):
def __enter__(self):
pushActiveCanvas(self)
def __exit__(self, *largs):
popActiveCanvas()
__enter__
und __exit__
definieren Sie, was passiert, wenn ein Kontextmanager eingegeben wird (vor der ersten Zeile des eingerückten Codes nach dem with
anweisung) und beendet.
In diesem Fall wird die Leinwand einfach auf eine Stack dies definiert die aktuell aktive Zeichenfläche (und wird von dieser entfernt, wenn der Kontextmanager beendet wird).
In kivy.graphics.instructions.Instruction
, die scheinbare Basisklasse für alle Zeichenanweisungen, die übergeordnetes Element wird auf die aktuell aktive Zeichenfläche gesetzt:
self.parent = getActiveCanvas()
Andere Tipps
Tatsächlich, Color
und Ellipse
werden importiert aus kivy.graphics
etwas höher im Code:
from kivy.graphics import Color, Ellipse
Um Ihre Frage zu Namespaces zu beantworten, muss Python überhaupt nicht "wissen", aus welchem Namespace Variablen abgerufen werden.Es hat sehr einfache Namespace-Regeln im Vergleich zu Sprachen wie Java, die nacheinander nach Funktions-, Objekt-, Klassen-, globalen und Paketbereichen suchen.Python hat einen globalen Namespace (pro Modul) und einen Stapel lokaler Namespaces (z.verschachtelte Funktionen können auf die Variablen von äußeren Funktionen zugreifen).Es geht einfach die Liste der Bereiche durch, bis es den fraglichen Variablennamen findet.
Der with
die obige Aussage hat eine besondere Bedeutung, aber ich denke sogar with
kann keine neuen Variablen implizit in den lokalen Bereich einführen (es kann eine Variable explizit mit der as
klausel).