4

読みやすさを向上させるためにコードを別々のファイルに分散しようとしていますが、インポートされたファイル内で未定義のグローバル名が参照されているという問題が発生しています。呼び出されたときに必要なすべての値を意図的に関数に渡すよりも良い解決策はありますか?

私のコードは現在次のようなものです:

#foo.py

import bar

def main():
    a = 1
    b = bar.Bar()
    while True:
        a += 1
        b.incr()
        print a
        print b.c

if __name__ == '__main__':
    main()

#END foo.py

-

#bar.py

class Bar:
    def __init__(self):
        self.c = 0
    def incr(self):
        self.c += a

#END bar.py

NameErrorが発生します:グローバル名'a'が定義されていません。main()を次のように書き直す必要がありますか?

def main():
        b = new bar.Bar()
        while True:
            a += 1
            b.incr(a)
            print a
            print b.c

そして、incr()を次のように書き直します。

def incr(self,a):
            c += a

それとももっと良い方法はありますか?

ちなみに、上記のコードは大幅に抽象化されています。実際のコードには、いくつかの大きな辞書を含む、いくつかのタイプの多くの変数を渡す非常に多くのクラスと関数が含まれています。

前もって感謝します!

4

2 に答える 2

5

なぜ機能しないのかを知りたいだけの場合:

まず、mainグローバルaを設定するのではなく、ローカルを設定します。グローバルにしたい場合は、明示的にする必要があります。

def main():
    global a
    a = 1
    # ...

ただし、Pythonの「グローバル」はモジュールごとであるため、これで問題が解決することはありません。言い換えれば、それは単にを作成しfoo.aますが、あなたのコードは存在しないでbar.Barあろうを探しbar.aます。

import foo必要に応じてアクセスできfoo.aます。(この場合、循環依存関係は問題にならず、 2回実行されることはありません。)または、それがインポートされたif __name__ == '__main__'と想定して、を使用することもできます。または、からの辞書に挿入することもできます。または他の多くのトリック。しかし、これらはすべて恐ろしいことです。foosys.modules['foo'].aabarfoo

グローバルな作業ができない場合、正しい答えはほとんどの場合、グローバルを使用しないことです。(実際、グローバルな仕事ができる場合でも、それは通常正しい答えです。)

それで、どうやってそれをしますか?詳細を知らなければa、明示的なモジュールグローバル、クラス属性、インスタンス属性、パラメータなどとして属するかどうかを推測するのは困難です。しかし、何を表すかをincr考えれば、どれが最も理にかなっているのかを判断し、それを実行してください。a


コメントで、これらの構成変数がたくさんあることを提案しました。それらをすべてaでラップし、dictそれを各オブジェクトのコンストラクターに渡すと、dict作業が簡単になります。

さらに重要なことに、adictは可変オブジェクトへの参照です。それをコピーすると、同じオブジェクトへの別の参照が作成されます。

main.py:

def main():
    configs = {}
    configs['gravity'] = 1.0
    rock = rps.Rock(configs)
    rock.do_stuff()
    configs['gravity'] = 2.1
    rock.do_stuff()
if __name__ == '__main__':
    main()

rps.py:

class Rock(object):
    def __init__(self, configs):
        self.configs = configs
    def do_stuff(self):
        print('Falling with gravity {}.'.format(self.configs['gravity']))

これを実行すると、次のように出力されます。

Falling with gravity 1.0.
Falling with gravity 2.1.

値を変更していませんconfigs['gravity'](これは不変のフロートです。変更できません)が、別の値置き換えました(configs変更可能であるため、dict問題なく変更できます)。身元がわからない場合は、さまざまな場所で、などをid(self.configs)印刷してみてください。id(self.configs['gravity'])

于 2013-03-13T21:57:15.723 に答える
2

aの特性または構成である場合Bar、それはそのインスタンスまたはクラス属性である必要があります。

class Bar(object):
    class_step = 1
    def __init__(self, inst_step):
        self.inst_step = inst_step
        self.c = 0
        self.step_mode = 'class'
    def inc(self):
        self.c += Bar.class_step if self.step_mode == 'class' else self.inst_step
于 2013-03-13T21:53:28.337 に答える