2012-10-23 19 views
85

私は、グローバル変数の仕組みについて少し混乱しています。私は約50のファイルを持つ大きなプロジェクトを持っており、これらのファイルすべてに対してグローバル変数を定義する必要があります。ファイル間でグローバル変数を使用していますか?

# ../myproject/main.py 

# Define global myList 
global myList 
myList = [] 

# Imports 
import subfile 

# Do something 
subfile.stuff() 
print(myList[0]) 

私は他の方法

# ../myproject/subfile.py 

# Save "hey" into myList 
def stuff(): 
    globals()["myList"].append("hey") 

を以下のように、subfile.pymyListを使用しようとしている:私は何

は、以下の通り、私のプロジェクトでmain.pyファイルをそれらを定義しました試しましたが、いずれも機能しませんでした

# ../myproject/main.py 

# Import globfile  
import globfile 

# Save myList into globfile 
globfile.myList = [] 

# Import subfile 
import subfile 

# Do something 
subfile.stuff() 
print(globfile.myList[0]) 

そしてsubfile.pyの内側に私はこれでした:

# ../myproject/subfile.py 

# Import globfile 
import globfile 

# Save "hey" into myList 
def stuff(): 
    globfile.myList.append("hey") 

をしかし、再び、それは動作しませんでした。これをどのように実装すればよいですか?私はそれが2つのファイルが本当にお互いを知っていないとき(よくサブファイルはメインを知らない)、それがうまく動作しないことを理解していますが、ioの書き込みやピクルスを使わずに、私はしたくない。

+0

実際には、2番目のアプローチはうまく動作します。 main.pyは正しく "hey"を表示します。あなたは私が「それはうまくいかない」ということでより具体的になりますか? – rodion

+0

@rodion:サイクルをインポートする - サブファイル内のコードがglobfileをインポートしようとしました。本体がそれ自身をインポートします – jsbueno

+1

'NameError:name 'myList'が' main.py'行から定義されていません 'print(globfile.myList [0 ]) ' –

答えて

156

問題はmain.pyからmyListを定義しているが、subfile.pyはそれを使用する必要があります。この問題を解決するためのきれいな方法です:すべてのグローバルをファイルに移動する、私はこのファイルをsettings.pyと呼んでいます。このファイルには、グローバルを定義し、それらを初期化する責任がある:

# settings.py 

def init(): 
    global myList 
    myList = [] 

次に、あなたのサブファイルは、グローバルをインポートすることができます:サブファイルは、init()メソッドを呼び出していないことを

# subfile.py 

import settings 

def stuff(): 
    settings.myList.append('hey') 

注 - タスクがメインに属していることを。 py:

# main.py 

import settings 
import subfile 

settings.init()   # Call only once 
subfile.stuff()   # Do stuff with global var 
print settings.myList[0] # Check the result 

このようにして、グローバル変数を2回以上初期化することなく、目的を達成できます。ハイヴの答えは素晴らしい作品

+15

私は一般的なアプローチが好きですが、全体的にはそうではありません'init()'のものです。モジュールは最初にインポートされたときにのみ評価されるため、モジュールの本体でこれらの変数を初期化することはまったく問題ありません。 –

+8

+1カーク:私は同意します。しかし、私のアプローチは、メインプログラムが始まる前に他のモジュールがglobals.myListを変更することを防ぐ。 –

+2

これは、組み込み名であるglobals以外のものと呼ぶべきです。 PyLintは警告を出します:「組み込みのグローバル(再定義組み込み)の再定義」 – twasbrillig

12

from your_file import *を使用すると、問題を解決するはずです。これは、グローバルに利用できるようにすべてを定義します(もちろん、インポートのローカル変数は例外です)。例えば

##test.py: 

from pytest import * 

print hello_world 

と:

##pytest.py 

hello_world="hello world!" 
+3

あなたがそのような変数を1つ割り当てた場合を除いて – jsbueno

+2

私は個人的に参照が明示的(紛らわしくない)となるように' import * 'の使用を個人的に避けます。どのモジュールでも参照できますか? – ThorSummoner

+8

インポートしない*。グローバル変数は同期しなくなります。各モジュールは独自のコピーを受け取ります。あるファイルの変数を変更しても、別のファイルに反映されることはありません。 https://docs.python.org/2/faq/programming.html#how-do-i-share-global-variables-across-modules –

14

あなたは「モジュール」の変数としてPythonグローバル変数と考えることができます - そのように、彼らははるかに便利な、伝統的な「グローバル変数よりも」

グローバル変数は実際にはモジュールの__dict__で定義され、そのモジュールの外側からモジュール属性としてアクセスできます。

だから、あなたの例では:

# ../myproject/main.py 

# Define global myList 
# global myList - there is no "global" declaration at module level. Just inside 
# function and methods 
myList = [] 

# Imports 
import subfile 

# Do something 
subfile.stuff() 
print(myList[0]) 

そして:あなたの第二試みは完璧に動作し、実際にあなたが利用可能にしたい変数名を処理するために、本当に良い方法であるだろう

# ../myproject/subfile.py 

# Save "hey" into myList 
def stuff(): 
    # You have to make the module main available for the 
    # code here. 
    # Placing the import inside the function body will 
    # usually avoid import cycles - 
    # unless you happen to call this function from 
    # either main or subfile's body (i.e. not from inside a function or method) 
    import main 
    main.mylist.append("hey") 
2

グローバルにしかし、最後の行には名前の誤りがあります。その方法は次のとおりです。

# ../myproject/main.py 

# Import globfile  
import globfile 

# Save myList into globfile 
globfile.myList = [] 

# Import subfile 
import subfile 

# Do something 
subfile.stuff() 
print(globfile.myList[0]) 

最後の行を参照してください。 myListはサブファイルではなくglobfileのattrです。これはあなたが望むように動作します。

マイク

6

、ちょうど1コメント:あなたは、他のモジュール内のグローバルを使用していて、動的にグローバルに設定したい場合は、あなたがグローバル変数を設定した後

、他のモジュールをインポートするために注意を払います例えば:

# settings.py 
def init(arg): 
    global myList 
    myList = [] 
    mylist.append(arg) 


# subfile.py 
import settings 

def print(): 
    settings.myList[0] 


# main.py 
import settings 
settings.init("1st")  # global init before used in other imported modules 
         # Or else they will be undefined 

import subfile  
subfile.print()   # global usage 
7

sharing global variables across modulesで見るPythonのドキュメント:

The canonical way to share information across modules within a single program is to create a special module (often called config or cfg).

config.py:

x = 0 # Default value of the 'x' configuration setting 

Import the config module in all modules of your application; the module then becomes available as a global name.

main.py:

import config 
print config.x 

or

from config import x 
print x 

In general, don’t use from modulename import *. Doing so clutters the importer’s namespace, and makes it much harder for linters to detect undefined names.

関連する問題