Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep variable and dictionary that contains it consistent?

Tags:

python-3.x

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?

like image 352
Georgia S Avatar asked Nov 17 '25 12:11

Georgia S


2 Answers

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.

like image 136
Byte Commander Avatar answered Nov 19 '25 08:11

Byte Commander


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
like image 33
Sнаđошƒаӽ Avatar answered Nov 19 '25 10:11

Sнаđошƒаӽ