関数の引数を使用する方がグローバルを使用するよりも優れている理由はいくつかあります。
- 混乱の可能性を排除します。プログラムが大きくなると、どのグローバルがどこで使用されているかを追跡するのが非常に難しくなります。関数の引数を渡すと、関数が使用する値をより明確にすることができます。
- グローバルを使用すると、最終的に犯す特定の間違いがあります。これは、何が起こっているのかを理解するまで非常に奇妙に見えます。同じ関数内のグローバル変数の変更と読み取りの両方に関係しています。これについては後で詳しく説明します。
- グローバル変数はすべて同じ名前空間に存在するため、名前が重複するという問題がすぐに発生します。「index」という名前の 2 つの異なる変数が必要な場合はどうすればよいでしょうか。
index1
それらを呼び出すとindex2
、非常に混乱し、非常に速くなります。ローカル変数または関数パラメーターを使用することは、それらがすべて異なる名前空間に存在することを意味し、混乱の可能性が大幅に減少します。
ここで、同じ関数内のグローバル変数の変更と読み取り、および発生する可能性のある紛らわしいエラーについて説明しました。外観は次のとおりです。
record_count = 0 # Global variable
def func():
print "Record count:", record_count
# Do something, maybe read a record from a database
record_count = record_count + 1 # Would normally use += 1 here, but it's easier to see what's happening with the "n = n + 1" syntax
これは失敗します:UnboundLocalError: local variable 'record_count' referenced before assignment
待って、何?record_count
明らかにグローバルであるのに、ローカル変数として扱われるのはなぜですか? 関数でを割り当てなかった場合record_count
、Python はグローバル変数を使用します。しかし、値を に代入するときrecord_count
、Python はその意味を推測する必要があります: グローバル変数を変更するのか、それともグローバル変数をシャドウ (非表示) にしてローカルのみを処理する新しいローカル変数を作成するのか変数。また、Python はデフォルトで、あなたがグローバルを賢く扱っている (つまり、何をしているのか、なぜなのかを正確に知らずにグローバルを変更しない) と想定し、 という名前の新しいローカル変数を作成するつもりであると想定しますrecord_count
。
ただし、関数内で名前が付けられたローカル変数にアクセスしている場合record_count
、Python では、関数内で同じ名前のグローバル変数にアクセスすることはできません。これは、本当に厄介で追跡が難しいバグを回避するためです。つまり、この関数にローカル変数という名前が付けられている場合record_count
、代入ステートメントのために存在する場合、へのすべてのアクセスrecord_count
はローカル変数にアクセスしていると見なされます。ローカル変数の値が定義される前に、ステートメントにアクセスを含めます。print
したがって、UnboundLocalError
例外。
さて、読者のための演習です。UnboundLocalError
print ステートメントを削除し、例外がまだスローされていることに注意してください。理由がわかりますか?(ヒント: 変数に代入する前に、代入の右側の値を計算する必要があります。)
さて:本当に関数でグローバルrecord_count
変数を使いたいのなら、それを行う方法は Python のglobal
ステートメントを使うことです。代わりにグローバル変数に割り当ててください。」それが機能する方法は、関数の最初にあるだけですglobal record_count
(または他の変数名)。したがって:
record_count = 0 # Global variable
def func():
global record_count
print "Record count:", record_count
# Do something, maybe read a record from a database
record_count = record_count + 1 # Again, you would normally use += 1 here
これにより、最初に期待したことが行われます。しかし、うまくいけば、なぜそれが機能し、他のバージョンは機能しないのかが理解できます.