Python: совместное использование атрибута между классом и вложенным классом - PullRequest
1 голос
/ 14 января 2020

Есть что-то в косвенной ссылке на атрибут, который, по-видимому, я не понимаю. Если у меня есть класс, и я создаю вложенный класс, в котором есть переменная, указывающая на переменную класса parent / controller, я подумал, что она должна измениться при изменении переменной controllers.

Пример:

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()

, что приводит к

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

То, что я ожидаю, это то, что B_value тоже будет 1 в конце, поскольку оно указывает на A_value. Почему B_value не меняется? Честно говоря, я не понимаю, почему половина моего кода работает, если это не так. И мне тяжело придумать способ поиска правильного, я знаю, что на это определенно где-то есть ответ. (проверено в Python 2,7 и 3,7)

1 Ответ

2 голосов
/ 14 января 2020

Вы не меняете существующее значение , на которое ссылается атрибут A_value; вы меняете то, к чему относится само название. Это не влияет на исходный объект, на который все еще ссылается атрибут B_value. Вы захотите прочитать https://nedbatchelder.com/text/names.html для хорошего обзора того, как именно работают Python имен.

self.A_value = 10 заставляет self.A_value ссылаться на определенный объект в памяти; назовите его M1, который является int объектом, представляющим 10.

self.B_value = controller.A_value приводит к self.B_value ссылке на тот же объект M1.

controller.A_value = 1 не влияет M1 вообще; controller.A_value ссылается на новый объект (назовите его M2), который представляет 1. Объект B_value по-прежнему ссылается на M1.

...