with の使用 - どの変数がコンテキスト内にあるかを知る方法

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

  •  12-12-2019
  •  | 
  •  

質問

このキビのコード:

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 同じ名前空間内にありませんか?

役に立ちましたか?

解決

編集:この回答は少し長くなりましたので、要約を以下に示します。

  1. with self.canvas 現在のを定義します アクティブなキャンバス 次のコードブロックの場合。
  2. すべての描画命令は次のようなものです 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 ただし、条項)。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top