名前空間
まずは公式ドキュメントの一節を見てみましょう。
名前空間は、名前からオブジェクトへのマッピングです。
現在、ほとんどの名前空間は Python 辞書として実装されています。
中国語訳: 名前空間は名前からオブジェクトへのマッピングであり、ほとんどの名前空間は Python 辞書を通じて実装されます。
ネームスペースは、プロジェクト内での名前の競合を回避する方法を提供します。各名前空間は独立しており、関係がないため、1 つの名前空間に重複した名前が存在することはできませんが、異なる名前空間では影響なく重複した名前を持つことができます。
コンピュータ システムでの例を見てみましょう。フォルダ (ディレクトリ) には複数のフォルダを含めることができます。各フォルダに同じファイル名を付けることはできませんが、異なるフォルダ内のファイルには同じ名前を付けることができます。
通常、次の 3 つの名前空間があります。
- 組み込み名、Python 言語の組み込み名 (関数名 abs、char、例外名 BaseException、Exception など)。
- グローバル名 (グローバル名) は、モジュール内で定義された名前であり、関数、クラス、その他のインポートされたモジュール、モジュール レベルの変数および定数を含むモジュールの変数を記録します。
- ローカル名 (ローカル名) は関数で定義された名前で、関数パラメーターやローカルに定義された変数など、関数の変数を記録します。(クラス内でも定義されています)
名前空間の検索順序:
変数 tarzan を使用すると仮定すると、Python の検索順序は、ローカル名前空間 -> グローバル名前空間 -> 組み込み名前空間です。
変数 tarzan が見つからない場合、検索は放棄され、NameError 例外が発生します。
名前エラー: 名前「tarzan」が定義されていません。
名前空間のライフサイクル:
ネームスペースのライフサイクルはオブジェクトのスコープによって異なり、オブジェクトの実行が完了するとネームスペースのライフサイクルが終了します。
したがって、外部名前空間から内部名前空間のオブジェクトにアクセスすることはできません。
# var1 是全局名称
var1 = 5
def some_func():
# var2 是局部名称
var2 = 6
def some_inner_func():
# var3 是内嵌的局部名称
var3 = 7
次の図に示すように、同じオブジェクト名が複数の名前空間に存在できます。
範囲
スコープは、名前空間に直接アクセスできる Python プログラムのテキスト領域です。ここでの「直接アクセス可能」とは、名前への非修飾参照が名前空間内で名前を見つけようとすることを意味します。
中国語訳:スコープとは、名前空間に直接アクセスできる Python プログラムのテキスト領域です。ここでの「直接アクセス可能」とは、名前への非修飾参照が名前空間内でその名前を検索しようとすることを意味します。
Python プログラムでは、変数に直接アクセスすると、変数が見つかるまですべてのスコープが内側から外側にアクセスされ、見つからない場合は未定義エラーが報告されます。
Python では、プログラム変数はどこからでもアクセスできるわけではなく、変数に値が割り当てられている場所によってアクセス許可が異なります。
変数のスコープによって、プログラムのどの部分が特定の変数名にアクセスできるかが決まります。Python には 4 種類のスコープがあります。
4 つのスコープ:
L (ローカル) : 最内層には、関数/メソッド内などのローカル変数が含まれます。
E (囲み) : 非ローカル (非ローカル) および非グローバル (非グローバル) 変数が含まれます。たとえば、入れ子になった関数が 2 つあり、1 つの関数 (またはクラス) A に関数 B が含まれている場合、B の名前については、A のスコープは非ローカルになります。
G (グローバル) : 現在のモジュールのグローバル変数など、現在のスクリプトの最も外側の層。
B (組み込み) : 最終的に検索される組み込み変数/キーワードなどが含まれます。
ルールの順序: L –> E –> G –> B。
ローカルで見つからない場合はローカルで検索されます (クロージャなど)。見つからない場合はグローバルで検索されてから、組み込みで検索されます。
g_count = 0 # 全局作用域
def outer():
o_count = 1 # 闭包函数外的函数中
def inner():
i_count = 2 # 局部作用域
組み込みスコープは、builtin という標準モジュールによって実装されますが、変数名自体は組み込みスコープに配置されないため、使用するにはこのファイルをインポートする必要があります。Python 3.0 では、次のコードを使用して、どの変数が事前定義されているかを確認できます
。
>>> import builtins
>>> dir(builtins)
Python では、モジュール、クラス、関数 (def、lambda) のみが新しいスコープを導入します。他のコード ブロック (if/elif/else/、try/excel、for/while など) は新しいスコープは導入されません。これは、次のコードに示すように、これらのステートメントで定義された変数に外部からアクセスできることを意味します。
>>> if True:
... msg = 'I am from China'
...
>>> msg
'I am from China'
>>>
この例では、msg 変数は if ステートメント ブロック内で定義されていますが、引き続き外部からアクセスできます。
msg が関数内で定義されている場合、それはローカル変数であり、外部からアクセスすることはできません。
>>> def test():
... msg_inner = 'I am from China'
...
>>> msg_inner
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'msg_inner' is not defined
>>>
エラーメッセージから判断すると、msg_inner はローカル変数であり関数内でのみ使用できるため、未定義で使用できないことがわかります。
グローバル変数とローカル変数
関数内で定義された変数にはローカル スコープがあり、関数の外で定義された変数にはグローバル スコープがあります。
ローカル変数は宣言されている関数内でのみアクセスできますが、グローバル変数はプログラム全体からアクセスできます。関数が呼び出されると、関数内で宣言されたすべての変数名がスコープに追加されます。以下の例:
#!/usr/bin/python3
total = 0 # 这是一个全局变量
# 可写函数说明
def sum( arg1, arg2 ):
#返回2个参数的和."
total = arg1 + arg2 # total在这里是局部变量.
print ("函数内是局部变量 : ", total)
return total
#调用sum函数
sum( 10, 20 )
print ("函数外是全局变量 : ", total)
上記の例の出力は次のとおりです。
関数内のローカル変数:30
関数外のグローバル変数:0
グローバルキーワードと非ローカルキーワード
内部スコープが外部スコープの変数を変更する場合は、グローバル キーワードと非ローカル キーワードが使用されます。
次の例では、グローバル変数 num を変更します。
#!/usr/bin/python3
num = 1
def fun1():
global num # 需要使用 global 关键字声明
print(num)
num = 123
print(num)
fun1()
print(num)
上記の例の出力は次のとおりです。
1
123
123
#!/usr/bin/python3
def outer():
num = 10
def inner():
nonlocal num # nonlocal关键字声明
num = 100
print(num)
inner()
print(num)
outer()
上記の例の出力は次のとおりです。
100
100
次のコードが実行されると仮定する特殊なケースもあります。
#!/usr/bin/python3
a = 10
def test():
a = a + 1
print(a)
test()
上記のプログラムを実行すると、次のようなエラーメッセージが表示されます。
Traceback (most recent call last):
File "C:\Users\Lenovo\Desktop\test.py", line 7, in <module>
test()
File "C:\Users\Lenovo\Desktop\test.py", line 5, in test
a = a + 1
^
UnboundLocalError: cannot access local variable 'a' where it is not associated with a value
テスト関数内の はローカルで未定義であり、変更できないため、エラー メッセージはローカル スコープ参照エラーです。
a をグローバル変数として変更します。
#!/usr/bin/python3
a = 10
def test():
global a
a = a + 1
print(a)
test()
実行出力は次のとおりです。
11
関数パラメータを介して渡すこともできます。
#!/usr/bin/python3
a = 10
def test(a):
a = a + 1
print(a)
test(a)
実行出力は次のとおりです。
11