1

There's something about indirectly linking to an attribute that apparently I don't understand. If I have a class, and I create a nested class which has a variable that points to the parent/controller class variable, I thought it should change when the controllers variable changes.

Example:

class A():
    def __init__(self):
        self.A_value = 10
        print("A_value in A after init:     " + str(self.A_value))
        self.B = self.B(self)
        print("")
        print("A_value in A after B init:   " + str(self.A_value))
        print("B_value in B after B init:   " + str(self.B.B_value))

    class B():
        def __init__(self, controller):
            self.B_value = controller.A_value
            print("B_value in B after init:     " + str(self.B_value))
            controller.A_value = 1
            print("B_value in B after change:   " + str(self.B_value))

A()

which results in

A_value in A after init:     10
B_value in B after init:     10
B_value in B after change:   10

A_value in A after B init:   1
B_value in B after B init:   10

What I expect to happen is B_value to be 1 at the end too, since it points to A_value. Why doesn't B_value change? Honestly, I don't understand why half my code works if this doesn't. And I'm having a hard time coming up with a way to search for the correct, I know that this is definitely answered in some way somewhere. (tested in Python 2.7 and 3.7)

2
  • 1
    There is no subclasses in the code you posted. subclass != nested class Commented Jan 14, 2020 at 12:34
  • ok, I changed the post Commented Jan 14, 2020 at 12:46

1 Answer 1

2

You aren't changing the existing value that the A_value attribute references; you are changing what the name itself refers to. That has no effect on the original object still referenced by the B_value attribute. You'll want to read https://nedbatchelder.com/text/names.html for a good overview of how exactly Python names work.

self.A_value = 10 makes self.A_value reference a particular object in memory; call it M1, which is an int object representing 10.

self.B_value = controller.A_value results in self.B_value referencing the same object M1.

controller.A_value = 1 does not affect M1 at all; it makes controller.A_value refer to a new object (call it M2) that represents 1. The B_value object still refers to M1.

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

3 Comments

thanks for the Link, this is very helpful indeed. I'm amazed how I came this far without running into this issue.
maybe as a bit of addendum: so if I assign a mutable, for example 'self.A_value = [1]', and then referenced it with 'self.B_value = controller.A_value' and changed it via 'self.B_value[0] = 10', it would actually change the value (which explains why most of my code works anyways, because I'm using lists and dictionaries all over the place)
That change isn't really an assignment. It looks like an assignment, but it's really a mutating method call, equivalent to setattr(self.B_value, 0, 10). You aren't changing the references, only the object both refer to.

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.