В Python, как обновить атрибут на основе атрибута другого объекта, переданного в качестве аргумента? - PullRequest
0 голосов
/ 05 мая 2019

Хорошо, давайте начнем с кода, потому что он довольно явный:

class c_1:
    def __init__(self):
        self.a = 5

class c_2:
    def __init__(self,other_obj):
        self.other = other_obj
        self.b = self.other.a

obj_1 = c_1()
obj_2 = c_2(obj_1)
print(obj_2.b)
>>>5
obj_1.a = 8
print(obj_2.b)
>>>5

Это проблема.Я знаю, что второй вызов obj_2.b должен вернуть 5, но я хочу, чтобы он возвратил 8.

Я думаю, что я действительно хочу, чтобы значение obj_1.a было передано по ссылке для obj_2.b (этот пример довольно прост, но в моем реальном коде есть больше атрибутов из obj_1, которые использует obj_2.)

Есть ли способ, без вызова другого метода, автоматически обновлять obj_2.b, когдазначение obj_1.a меняется?Спасибо.

Ответы [ 2 ]

2 голосов
/ 05 мая 2019

Есть ли способ, без вызова другого метода, автоматически обновить obj_2.b, когда значение obj_1.a будет изменено? Спасибо

Ответ - нет.

Конструктор c_2 устанавливает значение b равным other_obj.a, и затем значение b фиксируется до тех пор, пока вы явно не измените его значение снова. Рассматривайте его как нормальную (скалярную) переменную - как только значение будет установлено, оно не изменится, пока вы явно не назначите ему новое значение.

Если вы хотите сослаться на значение a в c_2, вы всегда должны ссылаться на self.other.a, поскольку self.other - это ссылка на other_obj, которую вы передали конструктору.

1 голос
/ 05 мая 2019

Это возможно , но ваш пробег может варьироваться в зависимости от ваших вариантов использования:

Один из подходов, показанный ниже, заключается в реализации Var class, который обрабатывает это для вас;инкапсуляция значений внутри объекта обходит ', передаваемый по значению ', и открывает ' значения ' для изменчивости.вот неполный (и хрупкий) пример;Есть довольно много угловых случаев, чтобы сгладить его, чтобы он работал гладко, но чтобы ответить на ваш вопрос: да, это определенно возможно:

Другие подходы могут использовать inspect module, или metaclasses, илиреализация callbacks.

tkinter в стандартной библиотеке Python использует специализированные классы и метод обратного вызова.

class Var:
    def __init__(self, value):
        self._value = value

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, value):
        self._value = value

    def __repr__(self):
        return str(self._value)


class IntVar(Var):

    def __iadd__(self, other: int):
        self._value = self._value + other
        return self.value


class c_1:
    def __init__(self):
        self._a = IntVar(5)

    @property
    def a(self):
        return self._a

    @a.setter
    def a(self, value):
        self._a.value = value


class c_2:
    def __init__(self, other_obj):
        self.other = other_obj
        self.b = self.other.a


obj_1 = c_1()
obj_2 = c_2(obj_1)
print(obj_2.b)
obj_1.a = 8
print(obj_2.b)
obj_1.a += 2
print(obj_2.b)

Вывод:

5
8
10
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...