检查Python中的可变性?

Mat*_*ner 30 python immutability python-2.x python-3.x hashable

考虑以下代码:

a = {...} # a is an dict with arbitrary contents
b = a.copy()
Run Code Online (Sandbox Code Playgroud)
  1. 可变性在dicts的键和值中起什么作用?
  2. 如何确保对一个字典的键或值的更改不会反映在另一个字典中?
  3. 这与dict键的可混合约束有什么关系?
  4. Python 2.x和Python 3.x之间的行为有什么不同吗?

如何检查Python中的类型是否可变?

Kar*_*tel 19

1)密钥不能是可变的,除非你有一个可清除但也可变的用户定义的类.这就是强迫你的一切.但是,使用可散列的可变对象作为dict键可能是个坏主意.

2)不要在两个词之间共享值.共享密钥是可以的,因为它们必须是不可变的.在copy模块意义上复制字典绝对是安全的.在这里调用dict构造函数也是有效的:b = dict(a).您还可以使用不可变值.

3)所有内置的不可变类型都是可清除的.所有内置的可变类型都不可清除.对于可以清除的对象,它必须在其整个生命周期内具有相同的哈希值,即使它已被突变.

4)不是我知道的; 我在描述2.x.

如果类型不是不可变的,那么它是可变的.A型是不可变的,如果它是一个内置的不可变类型:str,int,long,bool,float,tuple,,也许一对夫妇别人,我忘了.用户定义的类型总是可变的.

如果一个对象不是不可变的,那么它是可变的.如果一个对象是递归地只包含不可变类型的子对象,则该对象是不可变的.因此,列表元组是可变的; 你不能替换元组的元素,但你可以通过列表界面修改它们,改变整体数据.

  • 重新不​​可变对象:"值可以更改的对象被认为是可变的;一旦创建它们的值不可更改的对象称为不可变.(包含对可变对象的引用的不可变容器对象的值可以在后者的时候改变值被更改;但是容器仍然被认为是不可变的,因为它包含的对象集合无法更改.因此,不变性与具有不可更改的值并不严格相同,它更加微妙.)"http:// docs. python.org/py3k/reference/datamodel.html#objects-values-and-types (3认同)
  • 用户定义的类型并不总是可变的。例如,声明 `class mytuple(tuple): pass` 创建一个不可变的用户定义类型。 (2认同)

Gle*_*ard 10

Python中的语言级别实际上没有任何可变性或不变性.有些对象无法改变它们(例如字符串和元组),因此它们实际上是不可变的,但它纯粹是概念性的; 在语言级别没有任何属性表明这一点,既不是你的代码也不是Python本身.

不可变性实际上与dicts无关; 将可变值用作键是完全正确的.重要的是比较和散列:对象必须始终保持与自身相等.例如:

class example(object):
    def __init__(self, a):
        self.value = a
    def __eq__(self, rhs):
        return self.value == rhs.value
    def __hash__(self):
        return hash(self.value)

a = example(1)
d = {a: "first"}
a.data = 2
print d[example(1)]
Run Code Online (Sandbox Code Playgroud)

在这里,example不是一成不变的; 我们正在修改它a.data = 2.然而,我们正在使用它作为哈希的关键而没有任何麻烦.为什么?我们正在改变的属性对等式没有影响:散列不变,并且example(1)总是等于example(1),忽略任何其他属性.

最常见的用法是缓存和memoization:缓存或不缓存属性不会在逻辑上更改对象,并且通常对相等性没有影响.

(我要停在这里 - 请不要一次问五个问题.)


Kab*_*bie 6

模块集合中有 MutableSequence、MutableSet、MutableMapping 。可用于检查预制类型的可变性。

issubclass(TYPE, (MutableSequence, MutableSet, MutableMapping))
Run Code Online (Sandbox Code Playgroud)

如果您想在用户定义的类型上使用它,则该类型必须从其中之一继承或注册为虚拟子类。

class x(MutableSequence):
    ...
Run Code Online (Sandbox Code Playgroud)

或者

class x:
    ...

abc.ABCMeta.register(MutableSequence,x)
Run Code Online (Sandbox Code Playgroud)