2

this is my first question, and combined with my being fairly noob feel free to tell me if there is a completely different way I should be going about this!

Anyways, I am building a program that involves coloring a map with the four color theorem in Python 2.7, attempting to use certain colors as much as possible, and I ran into a problem when running something like this code:

In one module:

class state:
    a = 0
    b = 0
    variable_list = [a,b]

Then I import that module into my main program:

from State import state  //State(uppercase "s") is the .py file with the state class in it

instance = state()

instance.a = 1

print instance.variable_list[0]

...and the program prints 0, despite changing it in the main program. Any thoughts on how to update instance.variable_list with the change?

4 Answers4

2

You have to think of Python variables in terms of pointers. Your question really boils down to the following:

>>> a = 42
>>> l = [a]
>>> a = 0
>>> print l[0]  # shouldn't this print 0?
42

The answer is no, because re-assigning a has nothing to do with the list l. The list contains pointers to certain objects in memory. l[0] happens to be pointing to the same object as a (the int 42). When we reassign a, we simply have it "point" to a new object in memory (the int 0). This has no bearing on the list l.

It looks like this:

a = 42
l = [a]

                      +----+
            a  -----&gt | 42 | &lt------ l[0]
                      +----+

a = 0

                      +----+
            l[0] ---&gt | 42 |
                      +----+

                      +---+
            a ------&gt | 0 |
                      +---+

Notice that l[0] has not changed.

arshajii
  • 127,459
  • 24
  • 238
  • 287
2

I'll cut to what I think you want to be doing.

class State(object):
    def __init__(self):
        self.a = 0
        self.b = 0
    @property
    def variable_list(self):
        return self.a, self.b

and usage:

state = State()

state.a = 1

state.variable_list
Out[23]: (1, 0)

Notable changes from your code:

  • You're grabbing an instance of State, so make the attributes instance attributes, not class attributes. I doubt you want every instance of State to share the same attributes.
  • @property decorator makes it so you can access variable_list just like it's a regular attribute, but you can customize the behavior of what it returns - in this case, a couple of instance attributes.
  • Inherit from object to get a "new-style" class. Trust me on this, there is essentially no reason to be using an old-style class nowadays.
  • Naming conventions. Classes start with upper case letters.
Community
  • 1
  • 1
roippi
  • 25,533
  • 4
  • 48
  • 73
0

When you update the variable a it does not update that instance but simply assigns it a different int with a completely different pointer. Therefore, this change does not reflect that change in the list as you expected it would.

You could either add a update method in your list that does:

def update():
    variable_list = [a,b]

and call it every time you update your variables.

Or, you could simply use a dictionary and do away with individual variables:

class state:
    variables = {'a': 0, 'b': 1}

x = state()
print x.variables['a']

x.variables['a'] = 1
print x.variables['a']

[OUTPUT]
0
1
sshashank124
  • 31,495
  • 9
  • 67
  • 76
  • 1
    This answer is somewhat misleading. You're not creating a copy (just try printing the `id()` of `a` and of `variable_list[0]`); rather, you're just redirecting the `instance.a` pointer to point elsewhere, which has nothing to do with `variable_list`. – arshajii May 02 '14 at 01:06
  • @arshajii, I have updated my answer. If you feel it is still somewhat inadequate, please feel free to edit it. Thank you very much. – sshashank124 May 02 '14 at 01:07
  • The edit is a step in the right direction, but the statement *"This is because ints are immutable objects"* is still not accurate; this has nothing to do with the immutability of ints -- try it with lists, for example. – arshajii May 02 '14 at 01:19
0

Let's take a look at your class code.

class state:
    a = 0
    b = 0
    variable_list = [a,b]

a becomes 0, b becomes 0. Therefore, the list "variable_list" becomes [0, 0]. You then proceeded to change a using this code:

instance.a = 1

Which worked. The objects instance a variable is indeed 1. However, variable_list is still [0, 0]! The list remained it's original value because the list itself wasn't changed. The code you ran to make the list is only ran once. To solve this, you can make a function to update variable_list based on the current values of a and b (not the original values). For instance you can make a function to update the variable list like so:

def updateVariableList(self):
    variable_list = [self.a, self.b]

when you call that function using instance.updateVariableList(), it will update the values of the list based on the current values of a and b. Now print instance.variable_list[0] will show the updated values.

aonbyte
  • 376
  • 1
  • 2
  • 10