1

以下のコードが demovar を装飾された関数に公開していない理由がわかりません。

def exposebasevar(function):
    def decorator(*args, **kwargs):
        demovar = 'Where am I?' # => or MyThreadSafeObjectHandle()
        return function(*args, **kwargs)
    return decorator

@exposebasevar
def usesexposedvariable():
    print demovar # this line will give an error

usesexposedvariable()

背景: 私は、すべての関数で使用される 1 つのグローバル変数を持つモジュールを持っています。今、私はそれをスレッドセーフにしたいので、デコレータを介してこの変数を利用できるようにしました。次に、デコレーターで、オブジェクトのどのインスタンスがスレッドに属しているかを把握し、それを渡すことができます。そうすれば、すべての関数の署名やコンテンツを変更する必要がなくなります。

これを設定する方法を知っている人はいますか?ありがとう。

4

3 に答える 3

3

それは動的スコープになります。非常に悪い考えであると広く考えられているため、Python を含むさまざまな言語ではまったくサポートされていません。非常に汚くて壊れやすいハックを引っ張りたくない限り、不可能です。私は実際にこれを標準の免責事項として含めていますが、そのような解決策を念頭に置いているからではありません. 私が提供できる「作業」に最も近いのは、バイトコードを書き直すことです。

代わりに、装飾された関数のパラメーターにします。または、長期的にはおそらくよりシンプルでより良いグローバルな卸売りを取り除きます.

def exposebasevar(function):
    def decorator(*args, **kwargs):
        demovar = 'Where am I?'
        return function(*args, demovar=demovar, **kwargs)  # <<
    return decorator

@exposebasevar
def usesexposedvariable(demovar):  # <<
    print demovar
于 2013-01-05T19:25:44.647 に答える
2

あなたのコードは、以下が機能しないのとまったく同じ理由で機能しません:

def f():
  print v   # NameError: global name 'v' is not defined

def g():
  v = 42
  f()

g()

最もクリーンな方法は、おそらく次のようdemovarに引数として渡すことfunctionです。

def exposebasevar(function):
    def decorator(*args, **kwargs):
        demovar = 'Where am I?' # => or MyThreadSafeObjectHandle()
        return function(*args, demovar=demovar, **kwargs)
    return decorator

@exposebasevar
def usesexposedvariable(demovar):
    print demovar # this line will give an error

usesexposedvariable()
于 2013-01-05T19:25:10.937 に答える
1

すべての関数で使用される 1 つのグローバル変数を持つモジュールがあります。今、私はそのスレッドセーフにしたい...

あなたが説明しているのは基本的にの目的ですthreading.local; 残念ながら、それを機能させるには、おそらくコードを少し変更する必要があります。問題は、スレッド ローカル オブジェクト自体がスレッド ローカルではないことです。その属性のみです。スレッド ローカル オブジェクトの属性を常に使用している限り、ほぼ透過的です。

于 2013-01-05T19:47:53.557 に答える