3

I have a variable

self.foo = 1

And a dictionary

self.foo_dict = {
    'foo_key' = self.foo
}

I would like to be able to change the value of self.foo and have it also change in self.foo_dict. If this was in C (and the dict was a struct), I'd just use a pointer.

Any suggestions? Is this even possible in Python?

Sнаđошƒаӽ
  • 16,753
  • 12
  • 73
  • 90
Georgia S
  • 602
  • 4
  • 14
  • 1
    Possible duplicate of [Python equivalent of pointers](http://stackoverflow.com/questions/2065105/python-equivalent-of-pointers). Instead of using an int as the value of foo, you can make a wrapper class, and use an object of that class. – Sнаđошƒаӽ Apr 29 '16 at 04:55

4 Answers4

4

Is this even possible in Python?

Answer 1: Not in a straight forward manner, because int is immutable. However...

Answer 2: There are workarounds for achieving what you want.

Instead of using int for your variable foo, you need to have a wrapper class for foo, since int is immutable, and any wrapper class you define is not.

Your wrapper class for foo:

class Foo:
    def __init__(self, val):
        self.foo = val
    def set(self, val):
        self.foo = val
    def __repr__(self):
        return str(self.foo)

Then, the class where you are having that consistent variable-dictionary pair could be something like this:

class A:
    def __init__(self):
        self.foo = Foo(1)
        self.foo_dict = {
            'foo_key': self.foo
            }
    def set_foo(self, newval):
        self.foo.set(newval)

Test run:

>>> a = A()
>>> a.foo
1
>>> a.foo_dict['foo_key']
1
>>> a.set_foo(20)
>>> a.foo
20
>>> a.foo_dict['foo_key']
20
Sнаđошƒаӽ
  • 16,753
  • 12
  • 73
  • 90
4

No need for wrapper classes!
Just make self.foo a property that accesses the value in your dictionary:

class Bar:
    def __init__(self, foo_):
        self.foo_dict = {}  
        self.foo = foo_

    @property
    def foo(self):
        return self.foo_dict["foo_key"]

    @foo.setter
    def foo(self, value):
        self.foo_dict["foo_key"] = value

    def show(self):
        print("foo={} ; foo_dict['foo_key']={}".format(
                        self.foo, self.foo_dict["foo_key"]))

b = Bar(1)
b.show()
b.foo = 2
b.show()
b.foo_dict["foo_key"] = 3
b.show()

See this code running on ideone.com

Properties look to the outside like normal instance member fields, but they are really custom functions that could do anything. This way the two foo(...) methods are called when the foo property is accessed. The one decorated with @property is the getter and the one decorated with @PROPERTYNAME.setter is obviously the setter. You could also restrict read or write access to the property by simply omitting one of the property methods.

Here, they redirect all actions to the dictionary. That way you have exactly one instance of a simple mutable variable, but multiple ways to access it.

The example above would result in this output:

foo=1 ; foo_dict['foo_key']=1
foo=2 ; foo_dict['foo_key']=2
foo=3 ; foo_dict['foo_key']=3

So as we can see, no matter whether we change the value in the dictionary or through the property, both names always point to the same variable.

Byte Commander
  • 6,506
  • 6
  • 44
  • 71
  • +1 for the property approach. I too wanted to do this just after I posted my first answer. However, your first sentence make me feel... a little nervous, you know what I mean? ;-) – Sнаđошƒаӽ Apr 29 '16 at 05:55
  • 2
    :D Thanks. But why bothering with additional wrapper classes and calling methods to get and set the values in there if we have a far more comfortable option where all the synchronizing is done automatically in behind and we don't have any interface change... – Byte Commander Apr 29 '16 at 05:58
  • I agree yours is better approach. Like I said, after I posted my first answer, I thought that it could also be done using property. But later I decided not to change my first answer. After all, if I did add the property approach too, you wouldn't have got the chance to post an answer here ;-) – Sнаđошƒаӽ Apr 29 '16 at 06:00
  • @ByteCommander Nice answer. It seems a little weird to me. As far as I know, when I write `b.foo`, the getter method must be called. So why I receive the value of variable `self.foo` instead of the dictionary you that you returned in the getter method (i.e. `foo(self)`)? – EbraHim Apr 29 '16 at 06:30
  • 2
    @EbraHim `foo` is a property, that means to the outside it acts like an ordinary instance member, same as if I initialized it with `self.foo = 1` anywhere, e.g. in the constructor method. But internally it's a pair of two functions, one getter and one setter that get implicitly called when you access the property. The `@property | def foo(self):` method is the getter and looks up the value mapped to "foo_key" in the dictionary `foo_dict`. That's where the value is stored. The `@foo.setter | def foo(self, value):` method is the setter, it stores the new `value` in the `foo_dict` with "foo_key". – Byte Commander Apr 29 '16 at 06:50
  • I like this approach! I've never used `@property` before. I'll give it a whirl. – Georgia S Apr 29 '16 at 19:35
  • This is a pretty cool way to bundle all the private variables up in a dictionary and effectively let you drop the leading underscore convention on those private variables. and allow you to set the public property directly in the init like `self.foo=` – Davos Apr 16 '18 at 07:38
1
>>> class Test(object):
    def __init__(self,foo):
        self.foo = foo
        self.foo_dict = {'foo_key': foo}
    def set_foo(self, foo):
        self.foo = foo
        self.foo_dict['foo_key'] = foo


>>> a = Test(1)
>>> a.foo
1
>>> a.foo_dict
{'foo_key': 1}
>>> a.set_foo(2)
>>> a.foo
2
>>> a.foo_dict
{'foo_key': 2}
>>> 
Sнаđошƒаӽ
  • 16,753
  • 12
  • 73
  • 90
EbraHim
  • 2,279
  • 2
  • 16
  • 28
-1

I did not fully understood your question but if your want to change the value of self.foo, you can do it directly using a dictionary. Suppose that you have some dictionary:

self.some_dict = {"valueA":1}

Considering that a dictionary functions by key to value pairs, you an change the value of valueA like this:

self.some_dict["valueA"] = some_value

Therefore, the value of the key is changed to some_value. As another possibility you can create a copy of a dictionary using dict.copy. With this you have another dictionary with the same values of the first, and then update with dict.update to add new elements or values in the keys. Something like this:

self.some_dict = {"value1":1}
self.other_dict = some_dict
self.other_dict.update("{"value2": 2}")

With this you can update the value2 to other_dict.

armatita
  • 12,825
  • 8
  • 48
  • 49
julian salas
  • 3,714
  • 1
  • 19
  • 20
  • Whoa whoa whoa, slow it dwon wihle you type, will ya! Tehre are too many seplling errors in yuor writing. And I don't tihnk you have understood the questoin well. – Sнаđошƒаӽ Apr 29 '16 at 05:44