【问题标题】:Python 2.7.13/3.6.1 str.replace changes original string inconsistently [duplicate]Python 2.7.13/3.6.1 str.replace 不一致地更改原始字符串[重复]
【发布时间】:2017-11-12 09:10:25
【问题描述】:

在 python 3 文档中,str.replace 被描述为:

str.replace(old, new[, count])

返回字符串的副本,其中所有出现的子字符串 old 都替换为 new。如果给定了可选参数 count,则仅替换第一个 count 出现。

据此,代码

old = [['z','b']]
new = []
new.append(old[0])

print(old == new)

new[0][0] = old[0][0].replace('z','a')

print([old,new,old==new])

应该返回

True
[[['z', 'b']], [['a', 'b']], False]

但是,在 python 2 和 3 中它实际上都返回:

True
[[['a', 'b']], [['a', 'b']], True]

意味着 old 已从 [['z','b']] 修改为 [['a', 'b']] 即使文档暗示它不应该这样做。但是,并不是文档措辞不当。 old 的值不会每次都改变。这取决于我们如何定义变量new。如果我们以不同但(看似)等效的方式定义 new:

old = [['z','b']]
new = [['z','b']]

print(old == new)

new[0][0] = old[0][0].replace('z','a')

print([old,new,old==new])

我们得到输出:

True
[[['z', 'b']], [['a', 'b']], False]

这是我们最初所期望的。在这两种情况下,在使用 str.replace 之前,old == new 的计算结果为 True。然而,根据用于将变量 new 设置为 [['z','b']] 的方法,str.replace 会更改 old 的值。

Python 如何“记住”变量 new 是如何定义的,并相应地更改其输出? Python 如何知道两个等价的新变量之间有什么不同?无论如何,为什么旧​​的价值会发生变化? str.replace 不应该只返回旧的修改副本而不是实际更改它吗?

【问题讨论】:

  • 这篇文章可能对您有所帮助:Facts and myths about Python names and values,由 SO 资深人士 Ned Batchelder 撰写。
  • 这里没有不一致的地方,replace 从来没有修改过字符串。
  • 请记住,字符串是不可变的,不能更改,而列表对象是可变的。在您的第一个示例中,您将 new[0] 设为与 old[0] 相同的列表对象,它不是副本。在第二个示例中,new[0] 列表是一个单独的列表对象,恰好与 old[0] 列表对象具有相同的值。
  • 另请参阅stackoverflow.com/questions/240178/… - 这是更准确的副本。

标签: python string python-2.7 python-3.x replace


【解决方案1】:

您不是 .append(..)ing old 的内容,而是 old 的引用 - 在 old 上使用 .copy() 或 .deepcopy() - 那么您有两个不同的值,它们不引用同一个对象.

基本上new 和old 在您的第一个用法中指向相同的数据,在您的第二个示例中它们指向不同的数据。

见How to clone or copy a list?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-24
    • 1970-01-01
    • 1970-01-01
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多