2016-10-20 5 views
2

EDIT:申し訳ありませんが、私はそれを考え出しました。(私が望むものは100%ではありません。それはexecfile()の機能だ、私はそこにあったのか分からなかったとは信じられない。グローバル変数を宣言する関数をインポートする

私はこの質問をどのようにフレーズするかわかりませんでした(それが私のGoogle検索ではこれに事実上何も出てこなかった理由です)...しかし、ここに行きます。私は何をしようとしているのか簡略化したバージョンを与えるつもりです。だから私はmain.pyextra.pyという2つのファイルがあるとしましょう。私は、コンソールでこれを実行する場合

# extra.py 

def setfoo(): # sets "foo" to 5 even if it is unassigned 
    global foo 
    foo = 5 

だから、非常に簡単:後者は次のようになります

>>> setfoo() 
>>> foo 
5 

今度はmain.pyにかけて引き返すてみましょう。私はextra.pyからすべてをインポートimport文に設定されます:

# main.py 

from extra import * 

setfoo() 
print foo 

すべてが最後の行まで正常に動作しますが、ただし、がfooにアクセスしようとすると、fooが実際にはファイルextra.pyの下に格納されているため、認識できません。 setfoo()を実行した後にすべてをインポートすると、fooがインポートされ、すべて正常に動作します。これと同じように:私はfrom...importの文の代わりに標準importステートメントを使用している場合代わり

# main.py 

from extra import * 

setfoo() 
from extra import * 
print foo 

extra.pyからのデータに直接アクセスではなく、コピーされていることから、すべてのものを再インポートする必要はありません。

# main.py 

import extra 

extra.setfoo() 
print extra.foo 

しかし、私は本当にextra.setfoo()私はsetfoo()を実行するたびに出て入力する必要がありますする必要はありません、また私はextra.py私は言った機能を使用するたびに再インポートしますか:これも動作します。私はこれに回避策があるかどうかを知りたい。理想的には、元のバージョンmain.pyで設定したコードが正しく動作するように、extra.pyを変更する方法があります。 (EDIT:複数の人がこれを誤解しているようです - extra.pyを変更したいと思っています.というコードを変更したくありません。私もextra.py(私はPHPのincluderequireステートメントに似たものを考えていますが、インポートされたコードはそのままコピーされ、ファイルに貼り付けられます)をインポートする別の方法を使用することを検討しますが、この変更されたimport文はまだ1行のコードに過ぎず、それほど時間はかかりません。言い換えれば、ファイル処理とexecステートメントを使用することは、おそらくこの目的にはあまり便利ではないでしょう。

execステートメントといえば、私が使用しているコーディング方法がどれほど悪いかは大変気にしません。このextra.pyファイルの実際のバージョンは、今から私のプロジェクトのほとんどすべてで使用する予定なので、実際にはこれを動作させるにはちょうど良い方法が必要です。余分なスペースを取らずにこのファイルをインポートするたびに私のコード。どんな助けもありがとう。

編集:これを読んでいる人の多くは、私が達成しようとしていることについてはっきりしていないようです。実際のコードはここにあります。これは、「インライン変数の割り当て」を実現するためのシンタックスハックです。

class use_obj(object): 
    def __rshift__(self, other): return other 

def use(**kwargs): 
    for var in kwargs: exec 'global ' + var + '; ' + var + ' = kwargs[var]' 
    return use_obj() 

構文は次のようになります:ここでは(あなたは別のファイルにインポートしようとしていない場合は正常に動作します)のコードである

print use(x = 5, y = 8) >> str(x) + " times " + str(y) + " equals " + str(x*y) 

コード自体は、かなり粗さが、私はインライン変数代入を実行する方法を常に望んでいました。インラインif文、リスト内包表記、lambda + reduce()などの理由があります。なぜなら、単に割り当てられた変数を返すことができない理由は、use(x = 5, y = 8)式(文ではありません)は、私がを使ってコードに押し込む奇妙なオブジェクトを返します0の演算子とuse()関数が魔法のように返された奇妙なオブジェクトは、私が__rshift__()関数を設定する方法によって消えます。

私はそれがこのように見えるとしたら、コードはその美しさと目新しさの多くを失うことになると思う:

print use(x = 5, y = 8) >> str(extras.x) + " times " + str(extras.y) + " equals " + str(extras.x*extras.y) 
+0

'extra.py'の初期化中にあなたが' foo'を設定していない何らかの理由がありますか?そうでなければ、 'foo = None'を設定することができます。 –

+0

私が言ったように、これは私が実際にやろうとしていることの単純化されたバージョンです。関数の実際のバージョンは、この変数が 'foo'を設定する方法で複数の変数を設定し、どの変数を設定するのかわからないです。それは窓の外です。 –

答えて

1

まず、 あなたがでfooへの参照を取得するためのsysモジュールの助けを取る必要があります余分なモジュール。

import sys 
from extra import * 

print('1. Foo in globals ? {0}'.format('foo' in globals())) 
setfoo() 
print('2. Foo in globals ? {0}'.format('foo' in globals())) 
# Check if extra has foo in it 
print('2. Foo in extra ? {0}'.format(hasattr(sys.modules['extra'], 'foo'))) 
# Getting foo explicitly from extra module 
foo = sys.modules['extra'].foo 
print('3. Foo in globals ? {0}'.format('foo' in globals())) 
print("Foo={0}".format(foo)) 

出力:

1. Foo in globals ? False 
2. Foo in globals ? False 
2. Foo in extra ? True 
3. Foo in globals ? True 
Foo=5 

後のユースケースの更新:

# extra.py 
import sys 

def use(**kwargs): 
    _mod = sys.modules['__main__'] 
    for k, v in kwargs.items(): 
     setattr(_mod, k, v) 

今すぐ任意のファイル遺跡でインポート、輸入を取得し、そのグローバル変数を更新extra.pyの変更同じ、

#myfile.py 
from extra import * 
print use(x = 5, y = 8), str(x) + " times " + str(y) + " equals " + str(x*y) 

出力:

None 5 times 8 equals 40 

None利用機能は何も返しませんと表示されます。

注:Pythonで少し楽しく過ごしたいのでない限り、あなたのユースケースに対してより良いpythonicソリューションを選択すると良いでしょう。

は、Pythonのスコープ規則のために参照してください。 Short Description of the Scoping Rules?

+0

「Pythonでやってみようとしています。上の私の編集を参照してください - そのようなもののいずれかが遠隔に "pythonic"と考えられることはありません。上に書いたことを処理しようとしてください。 –

+0

私は実際に 'globals()'が今行っていることを理解しようとするつもりはありませんが(私は以前にその関数について聞いたことさえありませんでしたが)、逆効果を得ているようです。私は 'extra.py'を修正することができます。それは私が触れたくない' main.py'です。 –

+0

更新を確認してください。その場合、main.pyを変更する必要はありません。 –

0

モジュールは、オブジェクトにバインドされた変数名で名前空間を持っています。 from extra import *を実行すると、extraの名前空間にあるオブジェクトを取得し、それらを新しいモジュールの新しい変数にバインドします。 setfooが一度も呼び出されていない場合、extraにはfooという変数がなく、新しいモジュールの名前空間にバインドするものはありません。

setfooが呼ばれていた場合、from extra import *が見つかりました。しかし、物事はまだファンキーになることができます。いくつかの代入集合がextra.foo42と仮定する。他のモジュールの名前空間はそれを知らないので、他のモジュールではfooはまだ5ですが、extra.foo42となります。

常にオブジェクトとそのオブジェクトを参照している可能性のあるオブジェクトとの違いに注意してください。オブジェクトはどの変数やコンテナを参照しているのか分かりません(ただし、参照数をカウントします)。変数またはコンテナが別のオブジェクトにリバウンドされても、他の変数またはコンテナのバインドは変更されません。

+0

ええ、それは私が周りのグーグルで少し学んだことです。 'extra.py'がインポートされたファイル(この場合は' main.py')の名前空間に変数を設定できる方法があるかどうか知っていますか?私はそれが私の問題を解決するだろうと思う。 –

+0

あなたはそれを行うことはできませんが、 'my_config = {'foo':5}'のように独自のコンテナの中に 'extra 'を入れることができますが、より良い解決策は'余分なインポート*'をしないことです。あなたはちょうど 'import extra'を実行し、どこでも' extra.foo'として変数を参照しました。誰もが 'extra'ネームスペースで同じオブジェクトを参照していました。つまり、モジュールはコンテナなので、参照しています。 – tdelaney

+0

それはオプションで、悲しいことだと思っています。これは、私が 'foo'ではなく' extra.foo'ではなくアクセスするという要件です。辞書のようなコンテナに入れても、やっていることは成し遂げられません。 –

0

詳細を知らないと、グローバル変数として宣言する代わりに、fooextra.py setfoo()関数に戻すことが考えられます。 - 1

Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win32 
Type "copyright", "credits" or "license()" for more information. 
>>> ================================ RESTART ================================ 
>>> 
5 
>>> 

はEDIT:

次に、外部関数から値にmain.pyとフィードにグローバルfooを宣言setfoo()

ここでは、セットアップ

#extra.py 

def setfoo(): # sets "foo" to 5 even if it is unassigned 
    #global foo 
    foo = 5 
    return foo 

#main.py 

from extra import setfoo 

global foo 

foo = setfoo() 
print foo 

結果であり、
OK、この問題では2をとります。

具体的な必要性がある場合は、__builtin__モジュールに変数を追加すると、__builtin__が含まれている限り、他のモジュールからグローバルとしてアクセスできます。

#extra.py 

import __builtin__ 

def setfoo(): # sets "foo" to 5 even if it is unassigned 
    global foo 
    __builtin__.foo = 5 


#main.py 

from extra import * 
setfoo() 
print foo 

出力:本当にあまりにたい場合は、extra.pyを変更せずに、あなたの変数をインポートすることができますどのように

>>> 
5 
>>> 
+0

「main」のコードを変更するのは嫌です。私がそれがインポートされる方法を変更するだけでない限り、pyはかなり質問の外です。これは実際に私が取り組んでいる本当に奇妙な構文の "ハック"のため、非常に特殊なニーズがあり、 'foo = setfoo()'のようなものを使うことはできません。声明ではない –

+0

'extra、py'を少し変更することができれば、上記の修正された解決策を参照してください。 –

+0

これははるか遠くにあるようですが、もし私がこれをやろうとすれば、私が他の人にそれを送るなら私のコードはうまくいかないでしょう。ちょうどそれを明確にするために、私は 'extra.py'を修正することができました。それは私の質問の主な目的でした。私はこのコードを動作させるために変更する必要はない、' main.py'です。 –

関連する問題