1

問題は正当な理由で Python を悪用することであるため、質問はあいまいです。プログラム入力としてpythonがあるとします:

scf() # produces F,C that are somehow available globally
ci() # uses F,C 

質問は、scf呼び出し元のモジュールを変更できますか?

そして2番目のケース:

F,C = scf() # F,C are not set globally.

したがって、基本的には値 (x) をキャプチャするか、グローバルに設定します。どうすればそれができますか?

4

3 に答える 3

1

これを共有するのは気分が悪くなりますが、CPython ではスタック フレームを変更できます。

import sys
def scf():
    frame = sys._getframe(1) #caller's frame (probably)
    frame.f_globals['F'] = 'F' #add/overwrite globals
    frame.f_globals['C'] = 'C'

def ci():
    print F, C

scf()
ci() # prints 'F C'

しかし、呼び出し元の名前空間を目に見えないように変更する必要があるのはなぜでしょうか? これは悪い設計の匂いがします。scf()ものを返すci()必要があり、それらを引数として受け入れる必要があります。あなたが行っていることについてもっと共有していただければ、より良いアプローチを提案できるかもしれません。

アップデート

したがって、Python プログラムである外部で実行される文字列の間で何らかの状態を維持しようとしています。これは Python で行うのは簡単です: 明示的な locals と globals 名前空間を保持し、execと friendsの呼び出し間で渡すだけです。

s1 = """
foo = 'bar'
"""

s2 = """
def myImpureFunction():
    global foo
    foo = 1
myImpureFunction()
"""

lvars, gvars = {}, {}

exec s1 in lvars, gvars
print gvars
exec s2 in lvars, gvars
print gvars

おそらく、ある程度の正気を保つために、実行間で 1 つの特別な var が保持されることをユーザーに保証できます。

s1 = """
stash.foo = 'bar'
"""

s2 = """
def myImpureFunction():
    stash.foo = 'foo'
myImpureFunction()
"""

from types import ModuleType

lvars = {'stash': ModuleType('stash')}

exec s1 in lvars
print lvars['stash'].foo
exec s2 in lvars
print lvars['stash'].foo
于 2013-01-16T05:43:22.073 に答える
1

私は通常、次のようなオブジェクト プールを作成することで、この問題に取り組みます。

>>> class Pool:
    from collections import namedtuple, defaultdict, OrderedDict
    namespace = defaultdict(OrderedDict)
    @staticmethod
    def add(ns='default', **kwargs):
        Pool.namespace[ns].update(kwargs)
    @staticmethod
    def pop(ns='default', *args):
        return [Pool.namespace[ns].pop(k) for k in args]
    @staticmethod
    def remove(ns):
        if ns == 'default':
            raise AttributeError
        del Pool.namespace[ns]
    @staticmethod
    def get(ns='default', **kwargs):
        if kwargs:
            return namedtuple(ns,kwargs.keys())(Pool.namespace[ns][k] for k in kwargs)
        else:

            return namedtuple(ns,Pool.namespace[ns].keys())(*Pool.namespace[ns].values())
    @staticmethod
    def ns():
        return Pool.namespace.keys()
    @staticmethod
    def purge():
        Pool.namespace = defaultdict(OrderedDict)


>>> Pool.add('NS1',F=10,G=20)
>>> Pool.add('NS2',A=1,B=2)
>>> Pool.pop('NS1')
[]
>>> Pool.pop('NS1','F')
[10]
>>> Pool.get('NS1')
NS1(G=20)
>>> Pool.add(X=100,Y=200)
>>> Pool.ns()
['', 'NS1', 'NS2']
>>> Pool.remove('NS1')
>>> Pool.ns()
['', 'NS2']

>>> def sci():
    Pool.add("sci",F=20,G=30)


>>> def ci():
    ns_sci = Pool.get("sci")
    print ns_sci.F, ns_sci.G


>>> sci()
>>> ci()
20 30
>>> 

グローバル名前空間を汚染することなく、関数またはモジュール全体でこれを使用できるようになりました。複数の名前空間が共存できるように、名前空間全体に分散することもできます。

于 2013-01-16T06:26:22.440 に答える
0

クラスを作成できます:

class A(object):
    def scf(self):
        self.F = 10
        self.C = 20
    def ci(self):
        print self.F, self.C

アップデート:

または「スタンドアロン」クラス:

class B(object):
    @staticmethod
    def scf():
        B.F = 10
        B.C = 20
    @staticmethod
    def ci():
        print B.F, B.C

B.scf()
B.ci()
于 2013-01-16T05:37:50.073 に答える