How to modify variables of another scope?

不打扰是莪最后的温柔 提交于 2019-12-08 04:14:56

问题


Currectly, I'm trying the following: Some mutator function accepts other function's local scope using 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)

and that works as expected: I was able to modify mutable list contents but failed to 'rebind' another immutable int to the same name.

Currently, I see some options:

  • eval(), exec() & Co
  • Play with stack frames & local variables in mutator()
  • Keep such variables in a dict: not very handy but probably the best one

The restriction is: target function f() can contain just one function call, possibly with arguments, and that function should be able to alter values in f()s current scope.

So.. is there a way to reintroduce variable's value (bind another object) at runtime? I don't believe there is no good trick to achive this!


Here's an example of the thing I'm trying to achieve:

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']

I don't want to use data dict here: ability to modify them as local variables would be much better & pretty. Note that q QuerySet object is mutable & mutators can alter its contents.


回答1:


class AttributeCollection(object):
    pass
shared_settings= AttributeCollection()
# now improvise
shared_settings.temperature= 30
shared_settings.samples= []
# etc

Pass that shared_settings around, or make it global, and set its attributes to whatever you desire.

You see, the locals() of a function are just a namespace meant (and optimised for it) to be manipulated inside that function (and while that function is running). Use another namespace (in my suggestion, the shared_settings object) as a common playground for your code.




回答2:


Do it this way:

def mutator(l):
    l.append(10)
    return 10

def f():
    n = 1
    l = [1]
    n = mutator(l)
    print(n,l) # >>> 1, [1,10]

f()

Yeah, I know it isn't the clever hack you want; but it works. :-)

If you want a set of global configuration options that you can turn on and tune, stick all of them on an object:

class Settings(object):
    def __init__(self):
         self.n = 1
         self.l = [1]

Now you can change the variables to your hearts content.



来源:https://stackoverflow.com/questions/4444498/how-to-modify-variables-of-another-scope

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!