python-3.x - Python 使可变对象的行为不可变
问题描述
编辑:我没有改变对象的可变性,只是让变量表现得像它。我没有考虑具体的实现,但可能会使用它来使具有可变项的元组可散列
我知道在 python 中,您可以使不可变对象的行为类似于可变对象 - 特别是它们不可散列,并且您可以编辑对象而无需创建新对象 - 通过将其包含在列表中,因此它的行为类似于 C指针:
myVar = 5
myVar2 = myVar
#both point to same object 5
myVar += 1
#myVar2 still 5, myVar has new object 6
myVar = [5]
#myVar is no longer immutable
myVar2 = myVar
myVar[0] += 1
#myVar2 is now also 6
这意味着您可以更改变量指向的对象的值,它将影响引用该对象的所有变量
但是有没有一种相反的方法 - 使可变对象的行为不可变(并且是可散列的)?元组不会这样做 - 如果元组中的值是可变的,则可以更改它,并且具有可变对象的元组是不可散列的。我想这样做主要是为了它可以像不可变对象一样存储,其中具有相同值的变量都指向同一个对象,并且对变量的更改会导致新对象而不影响其他变量,或者我必须基本上用 OOP 重新实现 python 名称方法?
摘要:我想要一个可变对象的不可变包装器,与元组不同,它不允许编辑项目,并且是可散列的
解决方案
Python 没有变量。它有名字。所有名称都指向一个对象。
归因使名称指向对象。就是这么简单。您不能使归因隐含地生成新对象。
a = x
b = a # means the name "b" also refers to x - regardless if x is mutable or not
所以不,你不能以这种方式使可变对象不可变 - 如果有人获得对可变对象的引用,他们可以改变它,并且对同一对象的所有引用都会受到影响。
仅仅因为一个对象是不可变的,并不会使具有相同值的对象自动相同 - 试试这个:
>>> x = 'foo bar'
>>> y = ' '.join(['foo', 'bar'])
>>> x == y
True
>>> x is y
False
>>> id(x), id(y)
(139789175899936, 139789175899984)
如您所见,它们是两个不同的不可变对象,具有相同的值!两者分别存在于内存中!
但是,要使它们可散列是可能的-您必须定义一个__hash__
返回一些唯一散列的方法,当对象相等时比较相等-实际上,默认情况下,所有对象都已经将 id 作为散列返回,因此您可以包装在一个类中:
class HashableContainer:
def __init__(self, obj):
self._obj = obj
l = [] # mutable, no hash
ic = HashableContainer(l) # mutable, but hashable
d = {}
d[ic] = 'test' # can be used as key
但是有一个警告 - 如果您生成HashableContainer
具有相同内容的新对象,它将被视为不同的对象 - 因为它将具有不同的哈希(基于其 id)
推荐阅读
- javascript - 动态隐藏和显示更多文本到特定字符Javascript
- python - 使用一个键使用 Python 解析 XML
- pip - PIP 安装失败
- javascript - Html 图像源来自按比例缩小的原始图像
- java - 如何在java中用问号、点和感叹号分割字符串
- sprite-kit - 在 SpriteKit iOS 11.3.x 中,SKLabelNode 不渲染 £(英镑)货币
- mysql - 如何根据其他 2 个表的条件从一个表中检索数据?
- regex - perl:如何仅在文本文件中计算第二列中连续两个数字的差异
- json - 如何获取包含特定值的 JSON 节点?
- android-constraintlayout - ConstraintLayout 1.1.0 视图不能在同一条边上相互引用?