如何修改其他作用域的变量?
目前,我正在尝试以下方法:某个 mutator
函数使用 locals()
来接受其他函数的局部作用域。
def mutator(locals):
locals['n'] = 10
locals['l'].append(10)
def f():
n = 1
l = [1]
mutator(locals())
print(n,l) # >>> 1, [1,10]
f(None)
这个方法按预期工作:我能够修改可变列表的内容,但无法将另一个不可变的 int
重新绑定到同一个名字。
现在,我看到了一些选择:
eval()
、exec()
等等- 在
mutator()
中玩弄栈帧和局部变量 - 把这些变量放在一个
dict
中:虽然不太方便,但可能是最好的选择
限制条件是:目标函数 f()
只能包含一个函数调用,可能带有参数,并且那个函数应该能够改变 f()
当前作用域中的值。
那么……有没有办法在运行时重新引入变量的值(绑定另一个对象)呢?我不相信没有好的技巧可以实现这一点!
这是我想要实现的一个例子:
def view(request): # Yes, that's Django!
q = MyModel.objects.all()
data = { 'some_action': True, 'items_per_page': 50 } # defaults. Mutators can change this
mutators.launch(locals(), data ) # Launch mutators that may want to narrow the QuerySet
if data['some_action']: # do something useful if no mutator has disabled it
...
# paginate using data['items_per_page']
我不想在这里使用 data
字典:能够将它们作为局部变量修改会更好看,也更方便。请注意,q
的 QuerySet 对象是可变的,变更函数可以改变它的内容。
2 个回答
0
这样做:
def mutator(l):
l.append(10)
return 10
def f():
n = 1
l = [1]
n = mutator(l)
print(n,l) # >>> 1, [1,10]
f()
我知道这不是你想要的聪明方法,但它确实有效。:-)
如果你想要一组可以全局使用的配置选项,可以随意开启和调整,就把它们放在一个对象里:
class Settings(object):
def __init__(self):
self.n = 1
self.l = [1]
现在你可以随心所欲地修改这些变量了。
3
class AttributeCollection(object):
pass
shared_settings= AttributeCollection()
# now improvise
shared_settings.temperature= 30
shared_settings.samples= []
# etc
把那个 shared_settings
传来传去,或者让它变成全局的,然后把它的属性设置成你想要的样子。
你看,函数里的 locals()
就是一个命名空间,专门用来在这个函数内部操作的(而且是为了这个目的进行了优化)。所以,使用另一个命名空间(我建议用 shared_settings
对象)作为你代码的公共区域。