with の使用 - どの変数がコンテキスト内にあるかを知る方法
質問
で このキビのコード:
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
同じ名前空間内にありませんか?
解決
編集:この回答は少し長くなりましたので、要約を以下に示します。
with self.canvas
現在のを定義します アクティブなキャンバス 次のコードブロックの場合。- すべての描画命令は次のようなものです
Color
またはEllipse
アクティブなキャンバスに描画します。
名前空間は実際には何の関係もありません。重要なのはコンテキストです (以下を参照)。
の with
ステートメントを使用すると、いわゆる コンテキストマネージャー.
構文は次のとおりです
with thing [as foo]:
どこ thing
通常は、 contextlib.contextmanager
デコレーター。コンテキスト マネージャーが正確に何を行うかは、方法によって異なります。 thing
が実装されています。
ただし、スコープ内に変数を魔法のように表示させるだけではありません。コンテキストへの参照は、オプションの as foo
条項がありますが、それだけです。 Color
そして Ellipse
あなたの例では、他の場所(おそらくインポート)から来ています。
コンテキストマネージャーが正確に何であるかを調べるには、 with self.canvas
行がそうなっている場合は、 APIドキュメント または ソースコード のために kivy.graphics.instructions.Canvas
.
チュートリアルからの関連する抜粋は次のとおりです。
With Statementを使用することにより、適切にインデントされたすべての連続した描画コマンドがこのキャンバスを変更します。また、声明では、描画後、内部状態を適切にクリーンアップできることを確認します。
それで、 使用 の 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 には 1 つのグローバル名前空間 (モジュールごと) と、ローカル名前空間のスタック (例:ネストされた関数は外部関数から変数を取得できます)。問題の変数名が見つかるまで、スコープのリストを下に進みます。
の with
上記のステートメントには特別な意味がありますが、それでも with
新しい変数をローカル スコープに暗黙的に導入することはできません (1 つの変数を明示的に導入することはできます) as
ただし、条項)。