Я чувствую, что справедливость справедливо в своих рассуждениях здесь.
С другой стороны - я не могу удержаться от реализации доказательства концепции еще одной парадигмы программирования, «неестественной» для 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()