python - 使对象相对于其父级的父级不可变
问题描述
背景
如果用户定义的对象具有不可变对象作为属性,则在该属性上使用+=
运算符与在指向该属性的另一个变量上使用它具有不同的效果:
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
or 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。
我还尝试使用返回新类实例的__iadd__
方法将 X 实现为新类。这意味着x
它在应用时仍然表现得好像它是不可变的+=
,但我无法弄清楚如何同时实现上述要求 2 和 3。
我正在使用 Python 3。
解决方案
所需的行为完全取决于如何+=
为.x
例如,如果x
指向一个列表对象,则不会获得所需的行为,如果x
指向一个int
对象,则会获得该行为。
A
因此,对于您的班级或班级,您实际上没有任何事情可以或需要做任何事情B
来获得这种行为。
无论你做什么来获得这种行为,都必须以x
推荐阅读
- java - 如何在 Android Studio 中翻译按钮动画?
- geospatial - Geopandas geom_almost_equals 方法给出错误的输出
- java - 如何减小 Jar 文件的大小以进行更新或更新 Jar 文件的最佳方法是什么
- amazon-web-services - 让 EMR 集群在终止时终止其 EC2 实例
- erlang - config.exs 中 include_erts 的多个路径
- python - 加载 spacy 时出错 - 'en_core_web_sm' 库
- search - 如何退出 Tig 搜索视图?
- android - 当应用程序发生变化时的后台通知 React Native
- android - 多次单击按钮后,Android Mediaplayer 停止播放按钮单击声音
- haskell - div 中没有实例(整数浮点)