【问题标题】:Immutability in Python [duplicate]Python中的不变性[重复]
【发布时间】:2017-02-21 16:10:46
【问题描述】:

我试图了解不变性在 python 中是如何工作的。由于字符串在 python 中是不可变的,我希望每次执行字符串操作时 id 都会改变,但它不能按预期工作。 例子: t 上的最后一个操作不会改变它的 id。任何想法为什么?

【问题讨论】:

  • 我真的很讨厌这种优化如何违反 Python 语言语义。根据语言语义,t+= 之前和之后的值应该是具有(几乎)重叠生命周期的不同对象,因此它们应该不可能共享id

标签: python python-2.7 immutability


【解决方案1】:

我在不同的单元格[memory containing variables (I will not go to the bit level)]有一排苹果,其中一些是空的[cells containing garbage / empty value]

我拿出了一个。它在单元格 3 [logical address = 3]

我把它涂成蓝色(在我使用未来技术克隆它之后,用于不变性演示)[committed an operation on it, same could go for addition for integers]

我查看了放哪里,虽然 4 号单元是免费的,但 3 号单元也是(因为“原始”苹果已不存在了)!所以我把它放回了单元格 3 [and although we get a "new" apple, it has the same address]


t 也是如此(注意 id 是 CPython 中变量的内存地址),但由于我们在这里讨论的是“苹果链”(字符串由字符序列组成,所以我们有考虑我们必须继续序列的空间量,所以如果我的记忆看起来像(_ 代表任意垃圾数据,'^' 代表空间)

H e l l o _ _ _ _ _ B O O M
^ string pointer points here

我想将字符串更改为"Hello you",我可能会考虑使用空闲空间:

H e l l o ^ y o u _ B O O M
^ string pointer points here

但是如果我想将字符串更改为"Hello world!",我将不得不在其他地方寻找长度为"Hello world!" 的空闲空间(我们可能在"BOOM" 之后找到它,这很可能在垃圾中收集的环境,看看你的 ID 有什么不同):

H e l l o ^ y o u _ B O O M _ H e l l o ^ w o r l d ! _ G A R B A G E
                              ^ string pointer points here

【讨论】:

  • @B.M.那里的问题与实习的相似之处。我写的基本上就像Martijn在那里的评论 - "Python is free to reuse memory slots."
  • @B.M.我无法理解您所说的“它不会 [原文如此!] 那样工作”是什么意思。这个答案所描述的是 Python 正在为新字符串重用内存地址,因为前一个字符串被垃圾收集了。我查看了链接,但看不出它如何为问题中描述的现象提供替代解释。
  • 抱歉,太直接了。我发布一些东西来解释我的理解。我认为在这个例子中,蓝色苹果没有放在单元格 3 中,您只需将绿色的放在此处并在单元格 3 的末尾添加蓝色油漆。
  • 这是一个糟糕的解释。很难解释行、苹果或单元格应该是什么,也无法解释为什么我们可以“绘制”不可变的苹果或为什么单元格 3 是空闲的。
  • @user2357112 我将隐喻添加为蓝色 cmets。虽然我相信这很清楚。
【解决方案2】:

只要原始对象不再存在,对象的 ID 就可以重复使用。这不是特定于字符串,而是所有 Python 类型。举个最简单的例子,你可以检查一个简单的object的id:

>>> print id(object())
140437485756544
>>> print id(object())
140437485756544

但是,如果我们保留对前一个对象的引用,则 id 将不会被重用:

>>> a = object()
>>> id(a)
140437485756544
>>> b = object()
>>> id(b)
140437485756560

通过将中间结果(t 中的值)附加到列表中,您可以使用字符串在测试中重现相同的行为。

【讨论】:

  • 为什么在将“Test”附加到 t 的前两个测试用例中,id 发生了变化?这是“随机”还是python在这种情况下有系统地为字符串分配内存?
  • @PrestonM 不保证 id 会被重用 - 其他东西可能第一次占用了该内存位置(这是 CPython 实现 id 的方式)。可以保证的是活动对象的 ID 不会改变,并且没有两个不同的(活动的)对象将共享相同的 ID。
猜你喜欢
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-25
  • 1970-01-01
  • 2021-06-10
相关资源
最近更新 更多