为什么Python字符串是不可变的?使用它们的最佳实践

Ser*_*gey 49 python string immutability

  1. 使Python字符串不可变的设计原因是什么?它如何使编程更容易?
  2. 我已经习惯了可变字符串,比如C语言中的字符串.如果没有可变字符串,我应该如何编程呢?有没有最佳做法?

Fre*_*Foo 47

收到字符串后,您将确保它保持不变.假设您Foo使用字符串参数构造如下所示,然后修改字符串; 那个Foo名字会突然改变:

class Foo(object):
    def __init__(self, name):
        self.name = name

name = "Hello"
foo = Foo(name)
name[0] = "J"
Run Code Online (Sandbox Code Playgroud)

使用可变字符串,您必须始终制作副本以防止发生不良事件.

它还允许单个字符与长度为1的字符串没有区别,因此所有字符串运算符也适用于字符.

最后,如果字符串不是不可变的,则无法将它们可靠地用作a中的键dict,因为它们的哈希值可能会突然改变.

至于使用不可变字符串进行编程,只需习惯以对待数字的方式对待它们:作为,而不是对象.改变第一个字母name

name = "J" + name[1:]
Run Code Online (Sandbox Code Playgroud)

  • @wnnmaw larsmans的意思是你不能可靠地使用字符串作为dict的键,因为修改一个字符串会改变它的哈希值,这会改变字符串所用的桶.您可以通过尝试使用列表作为字典的键(`a = {}; a [[1,2]] = 1`抛出一个`TypeError`)来自己看清楚这个. (6认同)
  • Sooooooo我知道这有点晚了,但是你可以用可变字符串来解释你的意思吗?列表是可变的,但可以放在dicts中,什么会使可变字符串"不可靠"? (4认同)
  • 我不明白。如果您替换姓名的第一个字母,会发生什么不良后果?在这种情况下,如果我为 `name` 分配一个全新的值是不是一样? (3认同)

S.L*_*ott 11

与C字符串相比,不可变字符串极大地简化了内存分配:您不会猜测长度并且过度分配希望您过度分配.

它们更安全:你永远不会在C中以超出你的方式使用缓冲区.

只有一个可变字符串用例.

  • 替换子字符串或单个字符

所有其他字符串用例(连接,搜索等)的可变性并不重要.在所有其他情况下,可变性并不重要.

如果要在Python中替换字符或子字符串,只需创建一个新字符串即可

x = x[:place] + replacement + x[place+1:]
Run Code Online (Sandbox Code Playgroud)

这是唯一的新颖或独特的代码.


由于我无法理解的原因,添加以下内容似乎很重要.

"除了不可变的字符串之外,还有其他方法可以避免字符串缓冲区溢出."

出于这个问题的目的(特别是关于Python),不可变字符串具有无缓冲区溢出的令人愉快的结果.对于其他语言,适用其他原则,规则和细微差别.

  • Ruby(作为一个例子)具有可变字符串,并且它具有自动内存管理并且不能具有缓冲区溢出.至于替换子串是唯一的用例,那么(就地 - )附加什么?-1 (3认同)
  • 我*正在*谈论Python,但为了对比可变字符串和不可变字符串(请注意,问题的一部分和所有答案),我提供了一个例子。这个例子不可能是在 Python 中,因为它只有不可变的字符串。特别是,Python 中不存在就地追加(不是“s = s + ...”的缩写形式,而是修改字符串对象的操作)。这就是我想要表达的观点。关于可变字符串可能进行的操作,但不可变字符串不可能进行的操作,您的答案是不完整的。 (2认同)
  • @DavidHeffernan:你“可以”做的事情似乎与这个问题无关。我认为这是一个关于不可变的Python字符串的问题。上下文切换再次让我感到困惑。我想我应该放弃尝试理解这些评论。 (2认同)

Dav*_*nan 8

  1. 不可变对象是自动线程安全的.
  2. 你会发现使用Python字符串与C中的字符串相关的极端痛苦相比很容易.


Raf*_*ird 7

不可变字符串可以是字典和类似数据结构中的键,而无需复制字符串.与其他方式相比,围绕不可变字符串创建可变包装更容易.