Python使可变对象的行为一成不变

时间:2018-07-13 19:40:57

标签: python-3.x

编辑:我没有改变对象的可变性,只是使变量表现得像它。我没有特定的实现方式,但可以使用它来使具有可变项的元组可哈希化

我了解在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名称方法?

摘要:我想要一个可变对象的不可变包装器,与元组不同,该可变对象不允许对项目进行编辑并且是可散列的

1 个答案:

答案 0 :(得分:1)

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)