utilizzando con - come conoscere le variabili che sono all'interno del contesto
Domanda
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))
A quanto pare Color
e d
e Ellipse
sono all'interno del namespace di self.canvas
, ma come si fa a sapere che Python userdata
non è all'interno dello stesso spazio dei nomi?
Soluzione
Modifica:Questa risposta ha un po ' lunga, quindi, ecco il riepilogo:
with self.canvas
definisce attualmente attivo tela per il seguente blocco di codice.- Tutte le istruzioni di disegno, come
Color
oEllipse
disegnare su active tela.
Gli spazi dei nomi non hanno davvero nulla a che fare con esso, è il contesto che conta (vedi sotto).
Il with
istruzione consente di utilizzare i cosiddetti contesto gestori.
La sintassi è simile a questo
with thing [as foo]:
dove thing
di solito è una funzione decorato con la contextlib.contextmanager
decoratore.Che cosa è esattamente un contesto manager non dipende da come thing
è implementato.
Ma che cosa non fare è rendere variabile magicamente appaiono nel vostro ambito.Un riferimento al contesto può essere ottenuta con l'opzionale as foo
la clausola, ma questo è tutto. Color
e Ellipse
nel tuo esempio sono venuta da qualche altra parte (probabilmente di importazione?).
Per scoprire che cosa esattamente il contesto manager in with self.canvas
linea non si deve guardare il La documentazione delle API o il il codice sorgente per kivy.graphics.instructions.Canvas
.
Ecco il relativo estratto dal tutorial:
Con l'istruzione, con essa, tutti i successivi comandi di disegno ben rientrato a modificare questa tela.L'istruzione con inoltre fa in modo che dopo il nostro disegno, stato interno può essere pulito in modo corretto.
Così il utilizzare di Color
e Ellipse
colpisce self.canvas
, ma non sono definiti in alcun modo l'istruzione with.
Guardando il codice sorgente, questo è come funziona:
def class CanvasBase(InstructionGroup):
def __enter__(self):
pushActiveCanvas(self)
def __exit__(self, *largs):
popActiveCanvas()
__enter__
e __exit__
definire che cosa succede se un contesto manager è inserito (prima della prima riga di codice indentato dopo il with
istruzione) e chiuso.
In questo caso, la tela viene semplicemente spinto su un stack che definisce attivo tela (e spuntato da esso se il contesto manager è uscito).
In kivy.graphics.instructions.Instruction
, l'apparente classe base per tutte le istruzioni per il disegno, la genitore è impostato su attivo tela:
self.parent = getActiveCanvas()
Altri suggerimenti
In realtà, Color
e Ellipse
vengono importati da kivy.graphics
un po 'più alto nel codice:
from kivy.graphics import Color, Ellipse
.
Per rispondere alla tua domanda sugli spazi dei nomi, Python non ha bisogno di "sapere" quale spazio dei nomi sta ricevendo le variabili.Ha semplici semplici regole dello spazio dei nomi rispetto alle lingue come Java, che la funzione di ricerca, oggetto, classe, globale e pacchetto antichi uno dopo l'altro.Python ha uno spazio dei nomi globali (per modulo) e una pila di spazi dei nomi locali (E.G. Le funzioni nidificate possono ottenere nelle variabili dalle funzioni esterne).Scende solo la lista degli ambiti finché non trova il nome della variabile in questione.
L'istruzione with
di cui sopra ha un significato speciale, ma penso che anche with
non riesca implicitamente introdurre nuove variabili nell'ambito locale (può introdurre una variabile esplicitamente con la clausola as
, però).