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 Answers 4

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  -----> | 42 | <------ l[0]
                      +----+

a = 0

                      +----+
            l[0] ---> | 42 |
                      +----+

                      +---+
            a ------> | 0 |
                      +---+

Notice that l[0] has not changed.

Sign up to request clarification or add additional context in comments.

1 Comment

thanks arshajii, this was very helpful! (and the pseudo-graphics with text was a nice touch)
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.

Comments

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.

Comments

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

3 Comments

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, I have updated my answer. If you feel it is still somewhat inadequate, please feel free to edit it. Thank you very much.
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.

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.