2016-06-14 11 views
4

pythonプロジェクトにはutilities.pyというファイルがあります。ファイルからpythonのutilファイルでグローバル変数を避ける

  1. 読み取り、valid.txt、すべての数字が含まれています。それは、など

    は、今私が持っている機能is_valid(number)、へを持ちたい、たとえばis_float(string)is_empty(file)ため、関数のみUTIL含まれていそれらは有効であり、それらをマップ/セットにロードする。

  2. numberの存在をマップで確認し、TrueまたはFalseを返します。

この関数は頻繁に呼び出され、実行時間はできるだけ小さくする必要があります。私はオープンを読んで、その関数が呼び出されるたびにvalid.txtと読むのは嫌です。私が思いついた唯一の解決策は、valid.txtをインポートしたときにグローバル変数valid_dictを1回ロードすることです。ローディングコードは、utilities.pyにメインとして書かれています。

私の質問は、それが悪い習慣とみなされるので、グローバル変数を使用せずにこれをどうやって行うのですか?グローバルを使用せずにこのようなタスクを実行するための良い設計パターンは何ですか?また、このファイルはutilファイルであることに注意してください。

+2

一つの方法は、あなたがコンセプトに精通しているクロージャを使用することですか? – cdarke

+1

"...グローバル変数を使用する...悪い習慣とみなされます" - 悪い習慣ではありません。ちょうどそれをすること自由に感じる。 –

+1

これは** utilities.py **内のグローバルなものに過ぎません**他のどこにいても "モジュールレベルの変数" –

答えて

4

以下は、クロージャの簡単な例です。辞書cacheは、外部関数(load_func)内にカプセル化されていますが、返された場合でも内部のスコープ内に残ります。 load_funcは内部関数をオブジェクトとして返し、オブジェクトを呼び出さないことに注意してください。 utilities.py

__main__

def _load_func(filename): 

    cache = {} 

    with open(filename) as fn: 
     for line in fn: 
      key, value = line.split() 
      cache[int(key)] = value 

    def inner(number): 
     return number in cache 

    return inner 

is_valid = _load_func('valid.txt') 

from utilities import is_valid     # or something similar 

if is_valid(42): 
    print(42, 'is valid') 
else: 
    print(42, 'is not valid') 

辞書(cache)作成は辞書内包表記を使用して行われている可能性が、私はあなたが閉鎖に集中したかったです。

+1

これはいくつかの有用な情報とともに、疑問に対する確固たる答えのようです。しかし、私はグローバル変数を使用することが依然として望ましい解決策であると考える傾向があります。 – camomilk

+1

十分に公正な、あなたの選択。クロージャを使用する利点の1つは、永続オブジェクト(このコンテキストではグローバルとは呼ばず)が外部関数内にカプセル化されていることです。グローバルを使用すると、同じモジュール内の名前の衝突に注意する必要があります。クロージャを使用すると、他のモジュールで関数を抽出して再利用することができます。しかし、モジュールが比較的小さく複雑でない場合は、従来のグローバルを使用することはOKです。私は、コードが時間の経過とともに小さくなることはめったになく、複雑さが少なくなることを観察することで終わります。 – cdarke

+0

私はクロージャの概念に新しかったですが、これを正しく理解しているかどうかを教えてください。 'is_valid'関数を呼び出す必要があるたびに、まずis_valid = load_func( 'valid.txt')'を使ってロードします。これは、基本的に将来の使用のために関数を作成します。これがロードが起こる場所です。それ以降の 'is_valid'の呼び出しは、ファイルのオープンとロードをやり直すことはありません。 – harishankarv

3

変数valid_dictはグローバルではなく、utilities.pyのローカルです。もしあなたがfrom utilities import *のようなことをしたら、それはグローバルになるでしょう。今度はとなり、パッケージを開発しているときに悪い習慣とみなされています。

しかし、このような場合は基本的に静的変数が必要です:valid_dict={}is_valid()に追加してください。この辞書は、一度だけインスタンス化され、関数が呼び出されるたびにdictvalid_dictで使用可能になります。

def is_valid(number, valid_dict={}): 
    if not valid_dict: 
     # first call to is_valid: load valid.txt into valid_dict 
    # do your check 

if -clauseにvalid_dictに割り当てたが、だけにそれを変更しないの操作を行います。例えば、キーvalid_dict[x] = yを設定したりvalid_dict.update(z)のようなものを使用することによって。

(PS:これは「ダーティ」または「非神託」と見なされた場合、私に教えてください)

+0

このソリューションは、必要以上に見知らぬものです... – skrrgwasme

関連する問題