サーチ…


構文

  • グローバルa、b、c
  • 非局所的なa、b
  • x =何か#はxを束縛する
  • (x、y)= something#はxとyを束縛する
  • x + = something#はxをバインドします。同様に他のすべての "op ="
  • del x#はxを束縛する
  • xは何かの中で:#binds x
  • 何かをxとする:#binds x
  • ExとExを除く:#ブロック内に#をバインドする

グローバル変数

Pythonでは、関数内の変数は、代入文の左側に表示される場合や、他のバインディングオカレンスが表示される場合に限り、ローカルと見なされます。さもなければ、そのようなバインディングは、グローバルスコープまでの囲み関数で検索されます。これは、代入文が決して実行されなくても当てはまります。

x = 'Hi'

def read_x():
    print(x)   # x is just referenced, therefore assumed global

read_x()       # prints Hi

def read_y():
    print(y)   # here y is just referenced, therefore assumed global

read_y()       # NameError: global name 'y' is not defined

def read_y():
    y = 'Hey'  # y appears in an assignment, therefore it's local
    print(y)   # will find the local y

read_y()       # prints Hey

def read_x_local_fail():
    if False:
        x = 'Hey'  # x appears in an assignment, therefore it's local
    print(x)   # will look for the _local_ z, which is not assigned, and will not be found

read_x_local_fail()   # UnboundLocalError: local variable 'x' referenced before assignment

通常、スコープ内の代入は、同じ名前の外部変数をすべてシャドウします。

x = 'Hi'

def change_local_x():
    x = 'Bye'
    print(x)
change_local_x()  # prints Bye
print(x)  # prints Hi

名前をglobal宣言すると、スコープの残りの部分では、モジュールのトップレベルで名前への割り当てが行われます。

x = 'Hi'

def change_global_x():
    global x
    x = 'Bye'
    print(x)

change_global_x()  # prints Bye
print(x)  # prints Bye

globalキーワードは、プログラムのトップレベルではなくモジュールのトップレベルで代入が行われることを意味します。他のモジュールでは、モジュール内の変数への通常のドット付きアクセスが必要です。

要約すると、変数xが関数に対してローカルであるかどうかを知るためには、関数全体を読む必要があります。

  1. global xが見つかった場合、 xグローバル変数です
  2. nonlocal xが見つかった場合、 xは囲み関数に属し、ローカルでもグローバルでもありません
  3. x = 5またはfor x in range(3)またはその他のバインディングを見つけた場合、 xローカル変数です
  4. それ以外のxは、いくつかの囲みスコープ(関数スコープ、グローバルスコープ、または組み込み関数)に属します。

ローカル変数

関数内で名前がバインドされている場合、デフォルトでは関数内でのみアクセスできます。

def foo():
    a = 5
    print(a) # ok

print(a) #  NameError: name 'a' is not defined

制御フロー構造体はスコープに影響を与えません(例外をexcept )が、まだ割り当てられていない変数へのアクセスはエラーです:

def foo():
    if True: 
        a = 5
    print(a) # ok

b = 3
def bar():
    if False:
        b = 5
    print(b) # UnboundLocalError: local variable 'b' referenced before assignment

共通の結合操作が割り当てあるforなどのループ、および拡張割り当てa += 5

非局所変数

Python 3.x 3.0

Python 3はnonlocalという新しいキーワードを追加しました。 nonlocalキーワードはスコープオーバーライドを内部スコープに追加します。 PEP 3104でそれに関するすべてを読むことができます。これは、いくつかのコード例で最もよく説明されています。最も一般的な例の1つは、インクリメントできる関数を作成することです。

def counter():
    num = 0
    def incrementer():
        num += 1
        return num
    return incrementer

このコードを実行しようとすると、 num変数が最も内側の関数に割り当てられる前に参照されるため、 UnboundLocalErrorが返されます。ミックスに非ローカルを追加しましょう:

def counter():
    num = 0
    def incrementer():
        nonlocal num
        num += 1
        return num
    return incrementer

c = counter()
c() # = 1
c() # = 2
c() # = 3

基本的にnonlocalは、外部スコープの変数に割り当てることができますが、グローバルスコープは割り当てられません。したがって、 counter関数でnonlocalを使用することはできません。なぜなら、グローバルスコープに代入しようとするからです。試してみると、すぐにSyntaxError得られSyntaxError 。代わりに、ネストした関数でnonlocalを使用する必要があります。

(ここに示す機能は、ジェネレータを使用して実装する方がよいことに注意してください)。

バインディングの発生

x = 5
x += 7
for x in iterable: pass    

上記のステートメントはそれぞれバインディングオカレンスです x 5示されるオブジェクトにバインドされます。このステートメントが関数内にある場合、 xはデフォルトで関数ローカルになります。バインディングステートメントのリストについては、「構文」を参照してください。

名前を検索するときにクラススコープをスキップする関数

クラスは定義時にローカルスコープを持ちますが、クラス内の関数は名前をルックアップするときにそのスコープを使用しません。ラムダは関数なので、関数スコープを使って理解が実装されているので、これはいくつかの驚くべき動作につながります。

a = 'global'

class Fred:
    a = 'class'  # class scope
    b = (a for i in range(10))  # function scope
    c = [a for i in range(10)]  # function scope
    d = a  # class scope
    e = lambda: a  # function scope
    f = lambda a=a: a  # default argument uses class scope
    
    @staticmethod  # or @classmethod, or regular instance method
    def g():  # function scope
        return a

print(Fred.a)  # class
print(next(Fred.b))  # global
print(Fred.c[0])  # class in Python 2, global in Python 3
print(Fred.d)  # class
print(Fred.e())  # global
print(Fred.f())  # class
print(Fred.g()) # global

このスコープの仕組みになじみのないユーザーは、 bc 、およびeclassを印刷することを期待するかもしれません。


PEP 227から:

クラススコープ内の名前にはアクセスできません。名前は最内周の関数スコープで解決されます。ネストされたスコープのチェーン内でクラス定義が発生すると、解決プロセスはクラス定義をスキップします。

命名とバインディングに関するPythonの文書から:

クラスブロックで定義される名前の範囲は、クラスブロックに限定されます。メソッドのコードブロックには拡張されません。これは、関数スコープを使用して実装されるため、これには内包とジェネレータの式が含まれます。これは、以下が失敗することを意味します。

class A:
    a = 42
    b = list(a + i for i in range(10))

この例では、Martijn Pietersによるこの回答の参照を使用しています。 この参照には、この動作の深い分析が含まれています。

delコマンド

このコマンドには、いくつかの関連した別個の形式があります。

del v

vが変数の場合、コマンドdel vは変数をスコープから削除します。例えば:

x = 5
print(x) # out: 5
del x
print(x) # NameError: name 'f' is not defined

del束縛の発生であることに注意してください。別の方法で明示的に指定しない限り( nonlocalまたはglobalを使用して)、 del vvを現在のスコープにローカルにします。外部スコープでvを削除する場合は、 del vステートメントと同じスコープでnonlocal vまたはglobal v使用します。

以下のすべてにおいて、コマンドの意図はデフォルトの動作ですが、言語によって強制されません。クラスはこの意図を無効にする方法で記述されるかもしれません。

del v.name

このコマンドは、 v.__delattr__(name)呼び出しをトリガーします。

意図は、属性name使用不可にすることです。例えば:

class A:
    pass

a = A()
a.x = 7
print(a.x) # out: 7
del a.x
print(a.x) # error: AttributeError: 'A' object has no attribute 'x'

del v[item]

このコマンドは、 v.__delitem__(item)呼び出しをトリガします。

意図は、オブジェクトvによって実装されたマッピングにitemが属していないことです。例えば:

x = {'a': 1, 'b': 2}
del x['a']
print(x) #  out: {'b': 2}
print(x['a']) # error: KeyError: 'a'

del v[a:b]

これは実際にv.__delslice__(a, b)呼び出します。

意図は、上記のものと同様ですが、単一の項目の代わりに項目の範囲であるスライスを使用します。例えば:

x = [0, 1, 2, 3, 4]
del x[1:3]
print(x) #  out: [0, 3, 4]

ガベージコレクション#delコマンドも参照してください。

ローカルスコープとグローバルスコープ

ローカルおよびグローバルスコープとは何ですか?

コードのある時点でアクセス可能なすべてのPython変数は、 ローカルスコープまたはグローバルスコープのいずれかにあります

説明には、ローカルスコープには現在の関数で定義されたすべての変数が含まれ、グローバルスコープには現在の関数の外部で定義された変数が含まれます。

foo = 1  # global

def func():
    bar = 2  # local
    print(foo)  # prints variable foo from global scope
    print(bar)  # prints variable bar from local scope

どの変数がどのスコープにあるかを調べることができます。組み込み関数locals()およびglobals()はスコープ全体を辞書として返します。

foo = 1

def func():
    bar = 2
    print(globals().keys())  # prints all variable names in global scope
    print(locals().keys())  # prints all variable names in local scope

名前の衝突はどうなりますか?

foo = 1

def func():
    foo = 2  # creates a new variable foo in local scope, global foo is not affected

    print(foo)  # prints 2

    # global variable foo still exists, unchanged:
    print(globals()['foo'])  # prints 1
    print(locals()['foo'])  # prints 2

グローバル変数を変更するには、keyword global使用します。

foo = 1

def func():
    global foo
    foo = 2  # this modifies the global foo, rather than creating a local variable

スコープは、関数本体全体に対して定義されています!

それが意味することは、関数の半分は変数を決してグローバルにすることはできず、その後は局所変数を決してグローバルにすることはできません。

foo = 1

def func():
    # This function has a local variable foo, because it is defined down below.
    # So, foo is local from this point. Global foo is hidden.

    print(foo) # raises UnboundLocalError, because local foo is not yet initialized
    foo = 7
    print(foo)

同様に、オポジト:

foo = 1

def func():
    # In this function, foo is a global variable from the begining

    foo = 7  # global foo is modified

    print(foo)  # 7
    print(globals()['foo'])  # 7

    global foo  # this could be anywhere within the function
    print(foo)  # 7

関数内の関数

関数内には多くのレベルの関数がネストされているかもしれませんが、いずれかの関数の中にはその関数とグローバルスコープのローカルスコープが1つしかありません。中間スコープはありません。

foo = 1

def f1():
    bar = 1

    def f2():
        baz = 2
        # here, foo is a global variable, baz is a local variable
        # bar is not in either scope
        print(locals().keys())  # ['baz']
        print('bar' in locals())  # False
        print('bar' in globals())  # False

    def f3():
        baz = 3
        print(bar)  # bar from f1 is referenced so it enters local scope of f3 (closure)
        print(locals().keys())  # ['bar', 'baz']
        print('bar' in locals())  # True
        print('bar' in globals())  # False

    def f4():
        bar = 4  # a new local bar which hides bar from local scope of f1
        baz = 4
        print(bar)
        print(locals().keys())  # ['bar', 'baz']
        print('bar' in locals())  # True
        print('bar' in globals())  # False

globalnonlocal (Python 3のみ)

両方のキーワードは、現在の関数にローカルではない変数への書き込みアクセスを取得するために使用されます。

globalキーワードは、名前がグローバル変数として扱われるべきであることを宣言します。

foo = 0  # global foo

def f1():
    foo = 1  # a new foo local in f1
    
    def f2():
        foo = 2  # a new foo local in f2
        
        def f3():
            foo = 3  # a new foo local in f3
            print(foo)  # 3
            foo = 30  # modifies local foo in f3 only
        
        def f4():
            global foo
            print(foo)  # 0
            foo = 100  # modifies global foo

一方、Python 3で利用可能なnonlocalNonlocal Variables参照)は、ローカルスコープから現在の関数のローカルスコープにローカル変数を取得します。

nonlocalPythonドキュメントから:

非ローカルステートメントは、リストされた識別子が、グローバルを除く最も近い囲みスコープ内の以前にバインドされた変数を参照するようにします。

Python 3.x 3.0
def f1():
    
    def f2():
        foo = 2  # a new foo local in f2

        def f3():
            nonlocal foo  # foo from f2, which is the nearest enclosing scope
            print(foo)  # 2
            foo = 20  # modifies foo from f2!


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow