0

Python のローカル変数とグローバル変数、およびグローバル オブジェクトについて質問があります。このコードを見てください:

var = 0

class Test():
    var = 0

test = Test()

def sum():
    Test.var += 1
    test.var += 1
    var += 1

sum()

そのコードを実行すると、「var += 1」の行でのみ例外がトリガーされます。前の 2 行は機能します。Python FAQ からこの質問を読みました。「Test」と「test」が参照されているので、関数の最初の 2 行でも例外はないと思います。メンバー「var」が割り当てられていますが、「Test」と「test」はメンバーを取得するために参照されるため、グローバルです。FAQ には次のように書かれています。

それで問題は...私の仮定は本当ですか?

4

3 に答える 3

2

これらの関数を見てください:

def f():
    var += 1

def g():
    var = var.__iadd__(1)

g関数が行うことのリテラル バージョンですf(もちろん、Python は最初のバージョンでオペコードを使用し、属性INPLACE_ADDを検索しません)。__iadd__

しかし、ご覧のとおりvar、これらの関数の両方で、名前が 1 回読み込まれ、1 回保存されます。したがって、変数を割り当てると、FAQ にあるように、最初にグローバルに宣言しない限りローカルになります。

では、まだ存在しないローカル変数をロードして合計1し、同じ名前で再度格納するにはどうすればよいでしょうか?

クラス属性は、次のことを行っているため機能します。

Test.var = Test.var.__iadd__(1)

varスコープ内に存在しますTest(そのため、検索して再割り当てすることができます)。

于 2012-08-28T02:29:09.850 に答える
1

「Test」と「test」が参照されているので、関数の最初の 2 行でも例外はないと思います。

正しい。varまた、定義したグローバル属性ではなく、クラス属性を参照します。

メンバー「var」が割り当てられていますが、「Test」と「test」はメンバーを取得するために参照されるため、グローバルです。

別の言い方をTestすれtestば、グローバル名前空間で利用できるのでTest.vartest.var機能します。

の値がvarで変更されていない場合は、その上の行でグローバルではなくクラス属性sum()が変更されているため、0 が返されます。Test合計にいくつかの s を追加printして削除するvar += 1

def sum():
    Test.var += 1
    print Test.var
    test.var += 1
    print test.var
    print var

sum()

...与えます:

1
2
0

しかし、sum 関数内で var に値を代入しようとすると、その行の前でもエラーが発生します。

>>> def sum():
...     Test.var += 1
...     print Test.var
...     test.var += 1
...     print test.var
...     print var
...     var += 1
...     print var
... 
>>> sum()
1
2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in sum
UnboundLocalError: local variable 'var' referenced before assignment

varは現在 sum() で値が割り当てられているため、ローカルと見なされますが、その行より前に定義されていません。(これは、python が「先読み」またはvariable scopesum() でチェックを行っていることを意味します。これは、再割り当てさprint varれる前に最初のエラーが発生したためです。代わりに置くと、同じエラーが発生します。)varvar = 50var += 1

グローバル変数を操作するには:

def sum():
    Test.var += 1
    print Test.var
    test.var += 1
    print test.var
    global var #added the global keyword
    print var
    var += 1
    print var

出力:

1
2
0    # notice that global var is still 0 because the above var+=1 are for Test.var
1

編集:私が言及した「先読み」動作について。それについて質問を投稿する予定でしたが、この回答でよく説明されています: https://stackoverflow.com/a/370380/1431750 (to Python variable scope error )

于 2012-08-28T02:48:16.557 に答える
0

本質的に、ルールはあいまいさを避けるためのものです。

var = 0 # a variable in the global namespace

class Test():
    var = 0 # this is a attribute of the Test class

test = Test()

def sum():
    Test.var += 1
    test.var += 1 # these explicity mention on which object the name 
                  # should be stored

    blah = var    # reads from a outer scope, but assigns to a local variable
    var = Test    # new local variable which shadows the outer name
                  # not great but understandable

    var += 1 # this looks like it assigns to a local variable
             # but since a name from a outer scope is read first,
             # Python is not sure what the programmer really want to do
             # (maybe assign to the outer scope, or first read it then shadow?)
             # instead of guessing Python raises an exception, 
             # forcing the programmer to use `global` or a different name
于 2012-08-28T02:40:10.213 に答える