我认为大法官在这里的推理是正确的。
另一方面-我无法抗拒为Python的另一种“非自然的”编程范例实现概念证明-我只是喜欢这样做。:-)
因此,我创建了一个类,其对象属性的定义与您的要求相同(并且可以动态创建)。就像我说的那样,它只是处于概念验证状态- 但是我认为,大多数常见错误(例如尝试在根本没有定义的作用域中访问变量)都应该引发错误,即使不是正确的错误(IndexError)例如由于堆栈下溢而不是AttributeError)
import inspect class DynamicVars(object): def __init__(self): object.__setattr__(self, "variables", {}) def normalize(self, stackframe): return [hash(tpl[0]) for tpl in stackframe[1:]] def __setattr__(self, attr, value): stack = self.normalize(inspect.stack()) d = {"value": value, "stack": stack} if not attr in self.variables: self.variables[attr] = [] self.variables[attr].append(d) else: our_value = self.variables[attr] if our_value[-1]["stack"] == stack: our_value[-1]["value"] = value elif len(stack) <= len(our_value): while our_value and stack != our_value["stack"]: our_value.pop() our_value.append(d) else: #len(stack) > len(our_value): our_value.append(d) def __getattr__(self, attr): if not attr in self.variables: raise AttributeError stack = self.normalize(inspect.stack()) while self.variables[attr]: our_stack = self.variables[attr][-1]["stack"] if our_stack == stack[-len(our_stack):]: break self.variables[attr].pop() else: raise AttributeError return self.variables[attr][-1]["value"] # for testing: def c(): D = DynamicVars() D.c = "old" print D.c def a(): print D.c a() def b(): D.c = "new" a() b() a() def c(): D.c = "newest" a() b() a() c() a() c()
@H_301_9@-出现了另一个类似的问题,我设计了一种不需要特殊名称空间对象的hack(但是它诉诸于使用cpython的内部功能,例如将locals()更新为实际变量:(适用于Python 3.8)
解决方法
我正在将一些代码从Lisp转换为Python。
在Lisp中,您可以使用let构造,其中引入的变量声明为special,因此具有动态范围。(请参阅http://en.wikipedia.org/wiki/Dynamic_scope#Dynamic_scoping)
我该如何在Python中做同样的事情?似乎该语言不直接支持此功能,如果为true,将有什么模仿的好方法?
-出现了另一个类似的问题,我设计了一种不需要特殊名称空间对象的hack(但是它诉诸于使用cpython的内部功能,例如将locals()更新为实际变量:(适用于Python 3.8)
我正在将一些代码从Lisp转换为Python。
在Lisp中,您可以使用let构造,其中引入的变量声明为special,因此具有动态范围。(请参阅http://en.wikipedia.org/wiki/Dynamic_scope#Dynamic_scoping)
我该如何在Python中做同样的事情?似乎该语言不直接支持此功能,如果为true,将有什么模仿的好方法?
-出现了另一个类似的问题,我设计了一种不需要特殊名称空间对象的hack(但是它诉诸于使用cpython的内部功能,例如将locals()更新为实际变量:(适用于Python 3.8)