3

Python でのグローバル変数の非常に奇妙な扱いに出くわしました。誰かがこれらの驚きを説明し、正当化できることを願っていました!

A) このコードは、期待どおりに 10 を出力します。

def func():
  print(a)
a = 10
func()

B) このコードは、早すぎる参照に関する例外をスローします。

def func():
  print(a)
  a += 1
a = 10
func()

C) しかし、このコードは期待どおり [10] を出力します:

def func():
  print(a)
  a.append(1)
a = [10]
func()

したがって、タイプaがその範囲を変更し、さらに、まだ到達していない後のステートメントが表示方法を変更することを収集できaます。関数の開始時に使用できることはわかってglobal aいますが、かなり冗長です。

奇妙なスコーピングを処理するために Python が使用しているルールを誰か教えてもらえますか?

4

2 に答える 2

5

2 番目のインスタンスはを再バインド aするため、コンパイラはそれに対するローカル アクセスを生成します。他の 2 つは を読み取るだけaなので、通常のグローバル スコープ検索が実行されます。

于 2012-07-25T09:00:07.213 に答える
4

基本的に、次の 2 つのルールがあります。

  1. (スコープ内の) 変数からのみ読み取る場合、Python はその名前の変数が見つかるまでスコープ チェーンを上に移動します。
  2. 変数に少なくとも 1 回書き込むと、Python は常に現在のスコープで変数を作成します。

ただし、#2 の動作は次のように変更できます。

  • モジュール レベルの変数を参照する名前が必要な場合は、 を使用できますglobal my_module_variable。に書き込むとmy_module_variable、Python はローカル変数を作成しません。
  • Python 3 の時点では、囲んでいるスコープ内の変数を名前で参照することもできますnonlocal my_non_local_variable。最も近い囲んでいるスコープ内の変数を参照させるために使用します。

コードの問題

B) You are using +=: 変数に書き込もうとしています。したがって、ルール番号 2 が有効であり、現在のスコープ内の変数に書き込みます。ただし、それから読み取る必要もあります ( print(a)) が、以前に書き込みを行っていないため、変数にはまだ値がありません。1.Python では、関数内でルールとルールを混在させることはできません2.

func()変数で作業したい場合は、次のa = 10ようにコードを変更できます。

>>>> def func()
        global a
        print(a)
        a += 1
>>>> a = 10
>>>> func()
10
>>>> func()
11
于 2012-07-25T09:13:38.110 に答える