2012-04-23 15 views
3

を与えることに:私は次の出力を得るVARS()私はこのコードを実行すると、Pythonは異なる出力

a = '1' 
vars()['a'] = '2' 
print a 

def bar(): 
    a = '1' 
    vars()['a'] = '2' 
    print a 

bar() 

2 

しかしを、私はこのコードを実行すると

私は以下の出力を得ます:

1 

私の質問は、なぜこのようなことが起こり、どのようにして2番目のケースに私に最初のケースと同じ解決策を与えることができるのですか?

編集:

が本当に解決策を見つけることができませんでしたが、私はそれの周りに小さなハックを見つけた...私はむしろexecを使用していますけど。私は結果を取得します

def bar(): 
    a = "a" 
    b = "b" 
    exec a+"="+b 
    print a 

bar() 

b 

誰かがより良い解決策を見つけることができれば、それは素晴らしいことでしょう。私はこのようにグローバル変数を設定したり、狂ったことをしているわけではないので、心配しないでください。

+2

私はこのクラスは違いがないと信じています。それは、ローカルスコープとグローバルスコープの問題です。 – delnan

+1

また、関数内からこのようにグローバル変数を設定しようとしていると、何かがひどく間違っている可能性があります。 – 9000

答えて

2

新しいスタイルクラスがデフォルトの__dict__の動作をオーバーライドしているように見えます。したがって、この使用方法をvars()に壊してしまいます。古いスタイルのクラスに影響する理由は不明ですが、関連している可能性があります。ドキュメント(http://docs.python.org/library/functions.html#vars)から


vars([object]) 戻り__dict__モジュールの属性、クラス、インスタンス、または任意の他のオブジェクトは__dict__属性です。

モジュールやインスタンスなどのオブジェクトには、更新可能な__dict__属性があります。ただし、他のオブジェクトでは、__dict__属性に書き込み制限が設定されている可能性があります(たとえば、新しいスタイルのクラスではdictproxyを使用して直接的な辞書の更新を防止します)。

引数なしでは、vars()はlocals()のように動作します。 localsディクショナリへの更新は無視されるため、localsディクショナリは読み込みにのみ役立ちます。


あなたはおそらくself. = valsetattr(self, 'x', val)があなたのクラスのケースでは動作しない理由についてはコメントしてもらえますか?

+3

ドキュメントのこの部分は鍵であるようです。「地方辞書は、ローカル辞書への更新が無視されるため、読み込みにのみ役立ちます。つまり、vars()が返すものを変更する必要はありません。 –

+0

私はそれがクラスの部分を削除しても同じ問題を抱えているので、クラスとは関係がないとは思いません。私は問題が機能内にあると信じています。私は自己を試みた。 = valとsetattr(self、 'x'、val)でも同じ結果が得られます。 – Dragonfly

1

vars()の結果への割り当ては定義されていません。したがって、さまざまなシナリオやPythonのバージョンや実装で異なる結果をもたらす可能性があります。この方法で局所変数を変更するのは面倒なことかもしれませんが(私はこれをregex groupdictの結果に一度使ってみました)、これは非常に移植性がなく、いつでも破損する可能性があります。

関連する問題