python创建变量,如何在Python中创建动态范围变量?

I am translating some code from lisp to Python.

In lisp, you can have a let construct with the variables introduced declared as special and thus having dynamic scope. (See http://en.wikipedia.org/wiki/Dynamic_scope#Dynamic_scoping)

How can I do likewise in Python? It seems the language does not support this directly, if true, what would be a good way to emulate it?

解决方案

I feel Justice is plain right in his reasoning here.

On the other hand -- I can't resist implementing proof of concept for still another programing paradigm "unnatural" to Python -- I simply love doing this. :-)

So, I created a class whose objects'attributes are scopped just like you require (and can be created dynamically). As I said, it is just in a proof of concept state - but I think most usual errors, (like trying to access a variable ina scope it is not defined at all) should have errors raised, even if not the proper ones (IndexError due to a stack underflow instead of AttributeError, for example)

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()

2020 update - Another similar question showed up, and I crafted a hack that needs no special namespace objects (but which resorts to using inner things from cPython, like updating the locals() to actual variables: https://stackoverflow.com/a/61015579/108205 (works with Python 3.8)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值