2024-05-14 21:46:35 发布
网友
这个问题是模糊的,因为问题是为了一个好的理由滥用Python。 假设我使用python作为程序输入:
scf() # produces F,C that are somehow available globally ci() # uses F,C
问题是,scf能否修改调用者的模块?你知道吗
scf
第二种情况:
F,C = scf() # F,C are not set globally.
所以基本上要么捕获值(x),要么全局设置。 怎么做?你知道吗
分享这个让我很不舒服,但在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()应该接受这些对象作为参数。如果你分享更多关于你正在做的事情,也许我们可以建议更好的方法。你知道吗
scf()
ci()
所以您试图在外部执行的字符串(Python程序)之间保持某种状态。在Python中这样做很简单:只需保留一个显式的locals和globals名称空间,并在^{} and 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
也许为了保持一些正常的外表,您可以向您的用户保证在运行之间会保留一个特殊的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
您可以创建一个类:
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()
我通常通过创建如下所示的对象池来解决这个问题
>>> 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 >>>
现在可以跨函数或模块使用它,而不会污染全局命名空间。您还可以跨命名空间分布它,以便多个命名空间可以共存。你知道吗
分享这个让我很不舒服,但在CPython中,您可以更改堆栈帧:
但是,为什么需要以不可见的方式更改调用者的名称空间?这有点设计不好的味道。
scf()
应该返回对象,ci()
应该接受这些对象作为参数。如果你分享更多关于你正在做的事情,也许我们可以建议更好的方法。你知道吗更新
所以您试图在外部执行的字符串(Python程序)之间保持某种状态。在Python中这样做很简单:只需保留一个显式的locals和globals名称空间,并在^{} and friends 的调用之间传递它。你知道吗
也许为了保持一些正常的外表,您可以向您的用户保证在运行之间会保留一个特殊的var:
您可以创建一个类:
更新:
或“独立”类:
我通常通过创建如下所示的对象池来解决这个问题
现在可以跨函数或模块使用它,而不会污染全局命名空间。您还可以跨命名空间分布它,以便多个命名空间可以共存。你知道吗
相关问题 更多 >
编程相关推荐