wiseboar
wiseboar

Reputation: 335

Python: attribute sharing between class and nested class

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)

Upvotes: 1

Views: 73

Answers (1)

chepner
chepner

Reputation: 532508

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.

Upvotes: 2

Related Questions