0

I want to use a python dict to store variable references and be able to assign the values pointed out by those references.

foo = "foo"
d = {'foo' : foo}
d['foo'] = "bar"
foo
// output: 'foo', but I want it to be 'bar'.

How can I accomplish this?

Edit: Some actual code.

settings = values["settings"] // This is a dict, such as {"metoder_alphasort" : "on"}
field_map = {"metoder_alphasort" : profile.metoder_alphasort}
for setting in field_map.keys():
    if settings.has_key(setting):
        if settings[setting] == 'on':
            field_map[setting] = True
# field_map[setting] is now True, but profile.metoder_alphasort is False
Metin Devekaya
  • 51
  • 1
  • 2
  • 8
  • 2
    Why can't you do `foo = 'bar'`? Why are you using the dict? What's your real problem? – Rik Poggi Apr 18 '12 at 08:17
  • 2
    ___Don't do this___. Yes, it's possible, but it's wrong. Either use a dictionary if you need to access it programmatically, or use a variable if you don't, but not both. – agf Apr 18 '12 at 08:24
  • What I'm using the dict for is a map that contains a key which is a string representing a variable name, and the value being the variable itself. I want to avoid using exec when I only have access to the key. – Metin Devekaya Apr 18 '12 at 08:28
  • Than why don't you just use a dict (without mixing variables)? Please [edit] your question and add there an actual example of how your code look like. Maybe this SO question will help you clear the idea: [How can I use a string with the same name of an object in Python to access the object itself?](http://stackoverflow.com/q/9396706/1132524) – Rik Poggi Apr 18 '12 at 08:31

3 Answers3

2

Python implements references to objects but it does not implement refs to variables. You can create a read-only binding to a local variable by using a local function:

foo = "foo"
def readfoo(newval):
     return foo
d["foo"] = readfoo
foo = "bar"
d["foo"]() # returns "bar"
foo = "baz"
d["foo"]() # returns "baz"

This, however, is read-only since local function can only read vars from outside scope (I believe in Python 3 there's the nonlocal keyword that changes this).

Depending on what you really want to achieve, the simplest workaround is to use one element lists instead. This way you wrap your values in objects (the lists) which can be referenced normally:

foo = ["foo"]
d["foo"] = foo
d["foo"][0] = "bar"
foo[0] # prints "bar"
Rafał Dowgird
  • 43,216
  • 11
  • 77
  • 90
1

Your idea won't work as strings are immutable - the value isn't changed, it is instead replaced. You could do something like this if you really felt the need to do it this way:

class MutableString:
    def __init__(self, string):
        self.string = string

    def __str__(self):
        return self.string

    def __repr__(self):
        return "MutableString("+repr(self.string)+")"

    def set(self, string):
        self.string = string

foo = MutableString("foo")
d = {'foo' : foo}
d['foo'].set("bar")
print(foo)

Which gives us bar as output.

Another option would be to create an alternative dict subclass that messes with __setitem__() to produce a result like you want. The issue is, this isn't how others reading your code will expect this stuff to work. You are much better off changing your code so it doesn't rely on this sort of thing.

Gareth Latty
  • 86,389
  • 17
  • 178
  • 183
  • 1
    Nobody should feel "the need to do it this way". Also it's not what the OP is tring to do. – Rik Poggi Apr 18 '12 at 08:29
  • @RikPoggi I'm simply explaining why it doesn't work as the OP wants, and going into more detail. – Gareth Latty Apr 18 '12 at 08:30
  • *"You could do something like this"* and *"another option would be"* is not explaining why it doesn't work, but suggesting bad practices. What the OP needs is the right data structure not an hack for his bad design. – Rik Poggi Apr 18 '12 at 08:36
  • @RikPoggi I said that mutability was the issue, and showed why a mutable item would work in the situation. I then go on to state that different design is a better approach. – Gareth Latty Apr 18 '12 at 08:41
  • Wow! You call those better approaches? – Rik Poggi Apr 18 '12 at 08:42
  • 1
    @RikPoggi I said a *different* design, not one of the ones I listed. The point of showing the code was to show the fragility of it and how ugly it is. It's a way of getting the point across that it's not the best method, I don't really see your issue with it. – Gareth Latty Apr 18 '12 at 08:46
1

You can use setattr(profile, "mtoder_autoalpha", newvalue) as an alternative to the settings dict. The way you do it won't work as you expect because strings(and booleans and tuples ...) are immutable, so when you change it its a new string you are creating, not editing the 'original' object/variable.

jadkik94
  • 7,000
  • 2
  • 30
  • 39