2

一部のモジュール内で定義されている関数のデフォルト値をオーバーライドする方法を理解しようとしています。次のコードを検討してください ( program.py):

# import the default & user defined settings
from default_settings import *
from my_settings import *

# import some functions, which might be dependent on the settings above
from functions import *

# call dummy_function from 'functions' - prints '1'
dummy_function()

# output SOME_DEFAULT - will be '1'
print SOME_DEFAULT

# re-import 'my_settings' - SOME_DEFAULT will now be '2'
from my_settings import *
print SOME_DEFAULT

ここにあるdefault_settings.py

DO_DEBUG = False
SOME_DEFAULT = 1

これがmy_settings.py、私が内部で使用したい人の値ですfunctions.py:

DO_DEBUG = True
SOME_DEFAULT = 2

これはfunctions.py、インポートする必要がdefault_settingsある場所です。そうしないと、NameError が発生します。汎用ライブラリのようにする必要があるmy_settingsため、ここではインポートしたくありません。functions.py

# if I leave this line out, then I get a 
# "NameError: name 'SOME_DEFAULT' is not defined"
from default_settings import *

# I don't want to add "from my_settings import *" here, because 'functions.py' 
# is supposed to be a generic library of functions.

# dummy decorator.
def do_profile(cond):
    def resdec(f):
        if cond:
            print "profiling!"
        return f
    return resdec


# dummy function depending on both 'DO_DEBUG' and 'SOME_DEFAULT'
@do_profile(DO_DEBUG)
def dummy_function(bla=SOME_DEFAULT):
    print bla

実行するpython program.pyと、次の出力が得られます。

1
1
2

これは予期されることです。1 つ目1は からdummy_function、2 つ目はinside1のインポートによるもので、は を再インポートした結果です。default_settingsfunctions2my_settings

dummy_functionを使用するだけで必要なデフォルト設定を上書きする方法はありますmy_settingsか? from default_settings import *の行を省略しようと思ったのですfunctionsが、 になってしまいましNameErrorた。からインポートfunctionsし、同時にすべての変数を に渡す方法はありますfunctionsか?

4

2 に答える 2

5

設定を別の方法でカプセル化する必要があります。現在、2 つの異なるモジュールを 2 つの異なる設定セットのコンテナとして使用しています。次に、これらのモジュールからすべての名前をインポートし、from my_settings import *によってインポートされた名前を上書きすることを期待しますfrom default_settings import *。の悪用ですimport

import一般に、モジュールを作成するときに定義された名前は、暗黙的に再定義されるべきではないと思います。from module import *グローバル名前空間で一連の名前を暗黙的に定義しているため、すでに悪いです。別の *インポートを使用してそれらの名前を暗黙的に再定義するのは恐ろしいことです。

私の提案は、辞書を使用して設定を保存するか、設定クラスを使用することです。最初のケースでは、次のようなことができます。

# settings.py
default_settings = {'foo': True, 'bar': False}
my_settings = {'foo': False}
current_settings = default_settings.copy()
current_settings.update(my_settings)

これで、どのモジュールでもimport settings次のようにアクセスできます。

foo = settings.default_settings['foo']
bar = settings.current_settings['bar']
settings.current_settings['bar'] = True

これらの設定に対する変更は、インポートされたすべてのモジュールに表示されsettingsます。

より複雑なアプローチは、Settingsクラスを使用することです。Settingsいくつかのデフォルトを定義します:

class Settings(object):
    def __init__(self, foo=None, bar=None):
        self.foo = foo if foo is not None else True
        self.bar = bar if bar is not None else False

さまざまなカスタム設定を作成できるようになりました。

# settings.py
default_settings = Settings()
my_settings = Settings(foo=False)
current_settings = my_settings.copy()
current_settings.foo = False    # pointless example

繰り返しますが、上記のように、import settingsそれらにアクセスしたり、変更を加えたりします。

# foo.py
import settings
bar = settings.current_settings.bar
settings.current_settings.foo = True

から継承しSettingsて、新しいデフォルトを作成することもできます。

class LocalSettings(Settings):
    def __init__(self, foo=None, bar=None):             # in Python 3, 
        super(LocalSettings, self).__init__(foo, bar)   # super().__... works
        self.foo = foo if foo is not None else True

等々。

于 2012-05-30T15:14:10.097 に答える
2

あなたの関数はfunctions.pyインポート時に定義されます-つまり、(program.pyで)あなたが

#start of file DO NOT "import functions" YET!!!
import default_settings
import my_settings

default_settings.DO_DEBUG=my_settings.DO_DEBUG
default_settings.SOME_DEFAULT=my_settings.SOME_DEFAULT

import functions 

その後、からの設定my_settingsが引き継ぐ必要があります。これがあなたが探している解決策であるかどうかはわかりませんが(私にはぴったりではありません)、このコード構造で他のオプションを見つけることはできません。

編集

すべての設定を手動でリセットする手間を軽減するために、おそらく次のinspectモジュールを使用できます。

#start of file DO NOT "import functions" YET!!!
import default_settings
import my_settings
import inspect

#pull out all of "my_settings" and apply them to "default_settings",
# but only if they don't start with an underscore (reserved)
members=inspect.getmembers(my_settings)
for k,v in members:
    if( not k.startswith('_') ):
        setattr(default_settings,k,getattr(my_settings,k))

import functions

しかし、これはまだ私にはぴったりではありません-私が好きではないのは、の動作がfunctionsインポートするタイミングに依存することです。これは、Pythonで通常見られるものではありません。あなたのコードは、ある種の再構築の恩恵を受けることができると思います。

于 2012-05-30T14:45:09.310 に答える