50

Pythonドキュメントからのローカル/グローバル/自由変数の定義:

名前がブロックにバインドされている場合、非ローカルとして宣言されていない限り、その名前はそのブロックのローカル変数です。名前がモジュールレベルでバインドされている場合、それはグローバル変数です。(モジュールコードブ​​ロックの変数はローカルおよびグローバルです。)変数がコードブロックで使用されているが、そこで定義されていない場合、それは自由変数です


コード1:

>>> x = 0
>>> def foo():
...   print(x)
...   print(locals())
... 
>>> foo()
0
{}

コード2:

>>> def bar():
...   x = 1
...   def foo():
...     print(x)
...     print(locals())
...   foo()
... 
>>> bar()
1
{'x':1}

自由変数は、関数ブロックで呼び出されたときに返されますがlocals()、クラスブロックでは返されません。


Code 1xグローバル変数であり、で使用されますが、で定義されていませんfoo()
ただし、によって返されるわけではないため、自由変数locals()ではありません。
私はそれが医者が言ったことではないと思います。自由変数の技術的な定義はありますか?

4

5 に答える 5

50

自由変数の定義:使用されますが、グローバルでもバインドされていません。

例えば:

  1. xコード1はグローバル変数であるため、無料ではありません。
  2. xバインドされた変数bar()であるため、コード2では自由ではありません。
  3. xで無料ですfoo()

Pythonは、クロージャのためにこの区別をします。自由変数は、現在の環境、つまりローカル変数のコレクションでは定義されておらず、グローバル変数でもありません。したがって、他の場所で定義する必要があります。そして、これがクロージャの概念です。コード2では、で定義されたfoo()上で閉じます。Pythonは字句スコープを使用します。つまり、インタプリタはコードを見るだけでスコープを判別できます。xbar()

例:は、で囲まれ、でバインドされているためx、の変数として知られています。foo()foo()bar()xbar()

グローバルスコープはPythonによって特別に扱われます。グローバルスコープを最も外側のスコープと見なすことは可能ですが、パフォーマンスのためにこれは行われません(私は思います)。xしたがって、無料グローバルなものにすることはできません。

免除

人生はそれほど単純ではありません。無料のグローバル変数が存在します。Pythonドキュメント(実行モデル)によると:

グローバルステートメントは、同じブロック内の名前バインディング操作と同じスコープを持ちます。自由変数の最も近い囲みスコープにグローバルステートメントが含まれている場合、自由変数はグローバルとして扱われます。

>>> x = 42
>>> def foo():
...   global x
...   def baz():
...     print(x)
...     print(locals())
...   baz()
... 
>>> foo()
42
{}

私はそれを自分で知りませんでした。私たちは皆、学ぶためにここにいます。

于 2012-10-16T16:33:11.033 に答える
7

私が理解したことから、ドキュメンテーションは確かに自由変数について少し曖昧です。プレーングローバルおよび字句的にバインドされた自由変数として扱われる自由グローバル変数があります。Eli Benderskyは、シンボルテーブルに関するブログ投稿でうまくまとめています。

残念ながら、Pythonのコアには、「自由」変数を構成するものについて読者を最初は混乱させる可能性のある速記があります。幸いなことに、整理しやすいのはごくわずかな混乱です。実行モデルのリファレンスには次のように書かれています。

変数がコードブロックで使用されているが、そこで定義されていない場合、それは自由変数です。

これは正式な定義と一致しています。ただし、ソースでは、「free」は実際には「字句的にバインドされた自由変数」(つまり、バインドが囲まれたスコープで見つかった変数)の省略形として使用され、「global」は残りのすべてのフリーを指すために使用されます変数。したがって、CPythonソースコードを読むときは、自由変数のフルセットには、特に「無料」としてタグ付けされた変数と「グローバル」としてタグ付けされた変数の両方が含まれることを覚えておくことが重要です。

したがって、混乱を避けるために、CPythonで実際に処理される変数を無料として参照する場合は、「字句的にバインドされている」と言います。

(強調鉱山)

この省略形が使用された理由は、おそらく、グローバルな自由変数がある場合、出力されるバイトコードにまったく変更がないためです。変数が「無料」の場合、またはそうでない場合でも、その名前のルックアップが両方の場合globalに使用されるという事実は変わりません。LOAD_GLOBALしたがって、グローバル自由変数はそれほど特別なものではありません。

一方、字句的にバインドされた変数は特別に扱われ、cellオブジェクトに囲まれます。オブジェクトは字句的にバインドされた自由変数__closure__のストレージスペースであり、特定の関数の属性に配置されます。LOAD_DEREFこれらのために、自由変数のために存在するセルを調べる特別な命令が作成されます。命令のLOAD_DEREF説明は次のとおりです。

LOAD_DEREF(i)

セルのスロットiに含まれるセルをロードし、変数ストレージを解放します

したがって、Pythonでは、自由変数は、状態を持つオブジェクトの定義が、状態を持つオブジェクトの別の定義に字句的に(つまり静的に)ネストされている状況でのみ、概念として違いを生みます。

于 2015-12-21T16:10:10.443 に答える
3

初心者が誤解を招かないように、上記のNikhilによるコメントは、「変数は値を格納するために予約されたメモリ位置にすぎません」で始まります。Pythonにとっては完全に間違っています。

Pythonには「名前」と「値」があります。値には名前ではなくタイプがあります。メモリスペースは、名前ではなく値用に予約されています。たとえば、コードの後半でx=1の後にx="a string"を続け、その後にx = [3、9.1]を続けることができます。これらの割り当ての過程で、名前xは最初に整数を指し、次に文字列を指し、最後にリストを指します。割り当てが完了すると、割り当ての左側の名前は、割り当ての右側の値を指すようになります。値は、変更不可(不変)または変更可能(変更可能)にすることができます。整数、文字列、タプルなどは不変です。リストなどは変更可能です。整数は不変であるため、次のような2つのステートメントがある場合:

x = 4

x = x +1

2番目のステートメントはxが新しい値5を指すようにし、xが指すメモリ位置の値を4から5に変更しません。

これは、たとえばC言語のモデルとは大きく異なります。

于 2018-11-30T08:07:58.460 に答える
2

Pythonで自由変数を宣言するための明示的なキーワードはありません。関数の定義とその内部および周囲のステートメントに基づいて、Pythonは変数を束縛変数、セル変数、および自由変数に分類します。

次の例は、前の段落で説明した変数をカプセル化する関数のコードオブジェクトを使用してこの概念を示しています。

def func(arg1, arg2=2):
    def inner_func(arg3=arg2):
        return arg1, arg3
    arg1, arg2 = None
    return inner_func

' func 'の場合:

arg1arg2束縛変数です

arg1は、 ' inner_func '内の自由変数であるため、セル変数です。

•自由変数はありません。

func.__code__.co_varnames

('arg1'、'arg2'、'inner_func')

func.__code__.co_cellvars

('arg1'、)

func.__code__.co_freevars

()

' inner_func 'の場合:

arg3束縛変数です

arg1自由変数です

•セル変数はありません

inner_func.__code__.co_varnames

('arg3'、)

inner_func.__code__.co_freevars

('arg1')

inner_func.__code__.co_cellvars

()

于 2017-06-04T12:31:21.383 に答える
0

変数は、値を格納するために予約されたメモリ位置に他なりません。これは、変数を作成するときに、メモリにいくらかのスペースを予約することを意味します。

変数のデータ型に基づいて、インタプリタはメモリを割り当て、予約されたメモリに何を格納できるかを決定します。したがって、変数にさまざまなデータ型を割り当てることにより、これらの変数に整数、小数、または文字を格納できます。

変数への値の割り当て

Python変数は、メモリスペースを予約するために明示的な宣言を必要としません。変数に値を割り当てると、宣言が自動的に行われます。等号(=)は、変数に値を割り当てるために使用されます。

于 2017-02-04T15:52:19.607 に答える