回答:
これはPythonとは関係ありません。グローバル変数はどのプログラミング言語でも良くありません。
ただし、グローバル定数は概念的にグローバル変数と同じではありません。グローバル定数は完全に無害です。Pythonでは両者の間の区別は慣例により、純粋である:CONSTANTS_ARE_CAPITALIZED
とglobals_are_not
。
グローバル変数が悪い理由は、関数が隠された(明白ではない、驚くべき、検出が難しい、診断が難しい)副作用を可能にし、複雑さが増し、スパゲッティコードにつながる可能性があるためです。
ただし、関数のプログラミングでも、アルゴリズムの最適化、複雑さの軽減、キャッシングとメモ化、または主に命令型のコードベースに由来する構造の移植の実用性のいずれでも、グローバルステートの正常な使用は許容されます(ローカルステートおよび可変性と同様)。
全体として、あなたの質問には多くの方法で答えることができるので、最善の策は「なぜグローバル変数が悪いのか」グーグルすることです。いくつかの例:
より深く行き、なぜ副作用がすべてであるか、そして他の多くの啓蒙的なことを知りたいなら、関数型プログラミングを学ぶべきです:
はい、理論的には、グローバル(および一般に「状態」)は悪です。実際には、pythonのpackagesディレクトリを調べると、そこにあるほとんどのモジュールが一連のグローバル宣言で始まっていることがわかります。明らかに、人々はそれらに問題を抱えていません。
特にpythonの場合、グローバルの可視性はモジュールに限定されているため、プログラム全体に影響を与える「真の」グローバルはありません。これにより、害が少なくなります。別のポイント:がないconst
ため、定数が必要な場合はグローバルを使用する必要があります。
私の実務では、関数内でグローバルを変更した場合、次のglobal
ように技術的にそれが必要ない場合でも、常にで宣言します。
cache = {}
def foo(args):
global cache
cache[args] = ...
これにより、グローバルの操作を追跡しやすくなります。
このトピックに関する個人的な意見は、関数ロジックでグローバル変数が使用されていることは、他のコードがロジックとその関数の予想される出力を変更し、デバッグを非常に困難にし(特に大きなプロジェクトで)、テストを困難にするということです。同じように。
さらに、コードを読んでいる他の人(オープンソースコミュニティ、同僚など)を検討すると、グローバル変数がどこに設定されているか、どこが変更されたか、反対にこのグローバル変数に何が期待できるかを理解するのに苦労します。分離された関数に、その機能は関数定義自体を読み取ることで決定できます。
クリーンで(ほぼ)バグのないコードには、可能な限り純粋な関数が必要です(純粋関数を参照)。純粋な関数とは、次の条件を持つ関数です。
外部変数がおそらく予期しない結果を引き起こす可能性があるため、グローバル変数を持つことは、両方ではないとしても、上記の少なくとも1つに違反しています。
純粋関数のもう1つの明確な定義:「純粋関数は、すべての入力を明示的な引数として受け取り、すべての出力を明示的な結果として生成する関数です。」[1]。入力およびおそらく出力の1つ(グローバル変数)が明示的に指定または返されないため、グローバル変数を持つことは純粋な関数の概念に違反します。
あなたはユニットテストと第一の原則(考慮すればさらにその上、Fの ASTテスト、I ndependentテスト、R epeatable、S ELF-検証およびT imely)は、おそらく(インディペンデントは、原則としてテスト違反するテストが依存していないことをどの手段お互いに)。
グローバル変数(常にではない)を持っていますが、ほとんどの場合(少なくともこれまで見てきたこと)は、結果を準備して他の関数に渡すことです。これもこの原則に違反しています。グローバル変数がそのように使用されている場合(つまり、関数Xで使用されるグローバル変数を関数Yで最初に設定する必要がある)、関数Xを単体テストするには、まずテスト/関数Yを実行する必要があります。
一方、他の人々がすでに述べたように、言語が定数をサポートしていないため、グローバル変数が「定数」変数として使用されている場合は、わずかに優れている場合があります。ただし、私は常にクラスを操作し、クラスメンバーとして「定数」を持ち、グローバル変数をまったく使用しないことを好みます。2つの異なるクラスがグローバル変数を共有するために必要なコードがある場合、おそらくソリューションをリファクタリングしてクラスを独立させる必要があります。
グローバルを使うべきではないと私は思います。しかし、それらが使用される場合、著者は、よりクリーンでほぼバグのないコードのために、いくつかの原則(おそらく上記のものと他のソフトウェアエンジニアリングの原則と優れた実践)を検討する必要があります。
それらは不可欠であり、画面は良い例です。ただし、マルチスレッド環境または多くの開発者が関与する場合、実際には多くの場合、疑問が生じます。アーキテクチャによっては、分析にコストがかかり、頻繁に必要になる場合があります。グローバル変数の読み取りは問題ありませんが、それへの書き込みは、たとえば単一スレッドまたはスレッドセーフクラスによって制御する必要があります。したがって、グローバル変数は、それ自体が悪であると見なされる結果によって発生する可能性のある高い開発コストの恐れを引き起こします。したがって、一般的には、グローバル変数の数を少なくすることをお勧めします。
eval
、import *
、文字列の連結、変数id
、属性影を)