[解決済み】Pythonでモジュール全体の変数を作成する方法は?[重複している]をクリックします。
質問
モジュール内部でグローバル変数を設定する方法はありますか?一番わかりやすい方法でやろうとすると、Pythonインタプリタが変数
__DBNAME__
が存在しない。
...
__DBNAME__ = None
def initDB(name):
if not __DBNAME__:
__DBNAME__ = name
else:
raise RuntimeError("Database name has already been set.")
...
そして、別のファイルでモジュールをインポートした後
...
import mymodule
mymodule.initDB('mydb.sqlite')
...
そして、トレースバックは
... UnboundLocalError: ローカル変数 ' DBNAME 代入前に参照された ...
何かアイデアはありますか?私は、以下のように、モジュールを使用してシングルトンをセットアップしようとしています。 こいつの を推奨しています。
解決方法は?
以下はその内容です。
まず、Pythonが本当に持っているグローバル変数は、モジュール・スコープの変数だけです。 本当の意味でグローバルな変数は作れません。できるのは、特定のスコープにある変数を作ることだけです。 (Pythonインタプリタ内で変数を作成し、他のモジュールをインポートすると、変数は一番外側のスコープにあり、Pythonセッション内でグローバルになります)。
モジュール・グローバル変数を作るために必要なことは、ただ名前を割り当てることです。
この1行を含むfoo.pyというファイルを想像してください。
X = 1
今度は、それをインポートすることを想像してください。
import foo
print(foo.X) # prints 1
しかし、この例のように、モジュール・スコープ変数の1つを関数内のグローバル変数として使いたいとします。 Pythonのデフォルトは、関数変数はローカルであると仮定しています。 この場合、単に
global
という宣言を関数内で行い、その後にそのグローバルを使おうとします。
def initDB(name):
global __DBNAME__ # add this line!
if __DBNAME__ is None: # see notes below; explicit test for None
__DBNAME__ = name
else:
raise RuntimeError("Database name has already been set.")
ちなみに、この例では、単純な
if not __DBNAME__
なぜなら、空文字列以外の文字列値はすべて真と評価されるからです。したがって、実際のデータベース名はすべて真と評価されます。 しかし、0かもしれない数値の値を含む可能性のある変数については、単に
if not variablename
その場合は、明示的に
None
を使用しています。
is
演算子を使用します。 私はこの例を修正して、明示的な
None
のテストを行います。 の明示的なテストは
None
は決して間違っていないので、私はデフォルトでそれを使っています。
最後に、このページで他の人が指摘しているように、先頭の2つのアンダースコアは、変数をモジュールに対して "private"にしたいことを Python に通知します。 もし、あなたが
import * from mymodule
Pythonは先頭のアンダースコアが2つある名前を名前空間にインポートしません。 しかし、もしあなたが単純な
import mymodule
と言ってから
dir(mymodule)
を明示的に参照すると、リストの中に private" 変数が表示されます。
mymodule.__DBNAME__
Pythonはそれを気にせず、ただ参照させるだけです。 先頭の2つのアンダースコアは、モジュールのユーザがその名前を自分自身の値にバインドし直さないようにするための大きな手がかりとなります。
Pythonのベストプラクティスとされているのが
import *
を使うことで、結合を最小化し、明示性を最大化することができます。
mymodule.something
のようなインポートを明示的に行うか
from mymodule import something
.
EDIT: もし何らかの理由で、非常に古いバージョンのPythonでこのようなことをする必要がある場合、そのPythonには
global
キーワードを使えば、簡単に回避することができます。 モジュールグローバル変数を直接設定する代わりに、モジュールグローバルレベルでmutable型を使用し、その中に値を格納します。
関数内では、グローバル変数名は読み取り専用になり、実際のグローバル変数名をリバインドすることはできません。 (関数内でその変数名に代入すると、関数内のローカル変数名にのみ影響します)。 しかし、そのローカル変数名を使って、実際のグローバルオブジェクトにアクセスし、その中にデータを格納することは可能です。
を使用することができます。
list
しかし、あなたのコードは醜いものになるでしょう。
__DBNAME__ = [None] # use length-1 list as a mutable
# later, in code:
if __DBNAME__[0] is None:
__DBNAME__[0] = name
A
dict
がよいでしょう。 でも、一番便利なのはクラスインスタンスで、つまらないクラスを使えばいいんです。
class Box:
pass
__m = Box() # m will contain all module-level values
__m.dbname = None # database name global in module
# later, in code:
if __m.dbname is None:
__m.dbname = name
(データベース名の変数は、本当は大文字にする必要はありません)。
という構文が好きです。
__m.dbname
よりも
__m["DBNAME"]
それが最も便利な解決策だと思います。 しかし
dict
という解決策も有効です。
を使用すると
dict
を使用すると、任意のハッシュ値をキーとして使用できますが、有効な識別子である名前に満足する場合は、以下のような些細なクラスを使用することができます。
Box
を上記のようにします。
関連
-
Python 人工知能 人間学習 描画 機械学習モデル作成
-
[解決済み】 NameError: グローバル名 'xrange' は Python 3 で定義されていません。
-
[解決済み】終了コード -1073741515 (0xC0000135)でプロセス終了)
-
[解決済み] 関数内でグローバル変数を使用する
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] Pythonで静的なクラス変数は可能ですか?
-
[解決済み] JavaScriptの変数のスコープとは何ですか?
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】Pythonに三項条件演算子はありますか?
-
[解決済み】2つの辞書を1つの式でマージする(辞書の和をとる)には?)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
pythonを使ったオフィス自動化コード例
-
[解決済み] [Solved] sklearn error ValueError: 入力に NaN、infinity または dtype('float64') に対して大きすぎる値が含まれている。
-
[解決済み】なぜ「LinAlgError: Grangercausalitytestsから「Singular matrix」と表示されるのはなぜですか?
-
[解決済み】終了コード -1073741515 (0xC0000135)でプロセス終了)
-
[解決済み] builtins.TypeError: strでなければならない、bytesではない
-
[解決済み】syntaxError: 'continue' がループ内で適切に使用されていない
-
[解決済み] 'int'オブジェクトに'__getitem__'属性がない。
-
[解決済み] 関数内でグローバル変数を使用する
-
[解決済み] シングルトンを定義するシンプルでエレガントな方法はありますか?重複
-
[解決済み] 変数とメソッドでのアンダースコアとダブルアンダースコア [重複]