Фон
Если определенный пользователем объект имеет неизменяемый объект в качестве атрибута, то использование оператора +=
для атрибута имеет другой эффект, чем использование его для другой переменной, указывающей на этот атрибут:
class A():
def __init__(self):
# Set self.x to be an (immutable) int
self.x = 5
a = A()
Сейчас a.x == 5
a.x += 1
Теперь a.x
указывает на другой объект, а a.x == 6
.
x = a.x
Сейчас x
иa.x
указывают на один и тот же объект: id(x) == id(a.x) and x == a.x == 6
x += 1
Теперь x
и a.x
указывают на разные объекты, id(x) != id(a.x) and x == 7 and a.x == 6
Мой вопрос
Можно ли реализовать класс B
, имеющий атрибут a
, такой, чтобы оператор +=
работал таким же образом на b.a.x
?то есть Я хочу следующее поведение :
Требование 1
b = B()
Теперь я хотел бы b.a.x == 5
.
Требование 2
b.a.x += 1
Теперь я хотел бы b.a.x == 6
.
Требование 3
a = b.a
a.x += 1
Теперь я хотел бы b.a.x == 6
.Я не хочу, чтобы увеличение a.x
влияло на b.a.x
.
Требование 4
a = A()
b.a = a
Теперь мне бы хотелось b.a.x == 5
.
Требование 5
x = b.a.x
a = b.a
Теперь я хотел бы x == 5 and a.x == 5 and b.a.x == 5
.
Требование 6
x += 1
Теперь я хотел бы x == 6 and a.x == 5 and b.a.x == 5
.Я не хочу, чтобы увеличение x
влияло на a.x
или b.a.x
.
Другими словами, я хочу использовать оператор +=
для воздействия на b.a.x
, но только , когда он применяется непосредственно к b.a.x
, а не когда он применяется к другому имени, связанному с тем же объектом во время операции.
То, что я пробовал
Простое определение класса B не работает:
class B():
def __init__:
self.a = A()
Это не соответствует требованию 3.
Однако, если я изменю b.a
быть свойством, которое возвращает новую копию a
, тогда это тоже не работает:
class B()
def __init__:
self._a = A()
@property
def a(self):
return copy(_a)
@a.setter
def a(self, value)
self._a = value
Это не соответствует требованию 2.
Я такжепопытался реализовать X как новый класс с __iadd__
методом , который возвратил новый экземпляр класса.Это означало, что x
по-прежнему действовал так, как будто он был неизменным при применении +=
, но я не мог понять, как выполнить оба требования 2 и 3, описанные выше.
Я работаю в Python 3.