1

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
4
  • 2
    Why can't you do foo = 'bar'? Why are you using the dict? What's your real problem? Commented Apr 18, 2012 at 8: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. Commented Apr 18, 2012 at 8: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. Commented Apr 18, 2012 at 8: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? Commented Apr 18, 2012 at 8:31

3 Answers 3

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"
Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

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.

6 Comments

Nobody should feel "the need to do it this way". Also it's not what the OP is tring to do.
@RikPoggi I'm simply explaining why it doesn't work as the OP wants, and going into more detail.
"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.
@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.
@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.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.