Python中的"就地"字符串修改

Pau*_*han 20 python string

在Python中,字符串是不可变的.

逐个字符地逐字逐句地修改它的标准习惯是什么?

我能想到的唯一方法是与加入结果字符串相关的一些真正棘手的黑客攻击.

-

在C:

for(int i = 0; i < strlen(s); i++)
{
   s[i] = F(s[i]);
}
Run Code Online (Sandbox Code Playgroud)

这是超级表达,并准确地说我在做什么.这就是我要找的.

bst*_*rre 17

不要使用字符串,使用像bytearray这样可变的东西:

#!/usr/bin/python

s = bytearray("my dog has fleas")
for n in xrange(len(s)):
    s[n] = chr(s[n]).upper()
print s
Run Code Online (Sandbox Code Playgroud)

结果是:

MY DOG HAS FLEAS
Run Code Online (Sandbox Code Playgroud)

编辑:

由于这是一个bytearray,你不是(必然)使用角色.你正在使用字节.所以这也有效:

s = bytearray("\x81\x82\x83")
for n in xrange(len(s)):
    s[n] = s[n] + 1
print repr(s)
Run Code Online (Sandbox Code Playgroud)

得到:

bytearray(b'\x82\x83\x84')
Run Code Online (Sandbox Code Playgroud)

如果要修改Unicode字符串中的字符,您可能希望使用它memoryview,尽管它不直接支持Unicode.

  • 它们不是字符,只是字节.仅适用于ASCII,而不适用于Unicode. (2认同)
  • 适用于有效*字节*,而不仅仅是ASCII. (2认同)

Ned*_*der 17

你C的Python模拟:

for(int i = 0; i < strlen(s); i++)
{
   s[i] = F(s[i]);
}
Run Code Online (Sandbox Code Playgroud)

将会:

s = "".join(F(c) for c in s)
Run Code Online (Sandbox Code Playgroud)

这也很有表现力.它准确地说明了正在发生的事情,但是以功能风格而不是程序风格.

  • C对我来说很重要的一点就是它可以就地工作. (2认同)

kil*_*own 10

你可以使用UserString模块:

 >>> import UserString
... s = UserString.MutableString('Python')
... print s
Python
>>> s[0] = 'c'
>>> print s
cython
Run Code Online (Sandbox Code Playgroud)

  • 请注意,MutableString在Python 2.6中已弃用,并在Python 3中删除 - https://docs.python.org/2/library/userdict.html#UserString.MutableString (9认同)

Jav*_*ier 7

我会说最Pythonic的方法是使用map():

s = map(func, s) # func has been applied to every character in s
Run Code Online (Sandbox Code Playgroud)

这相当于写作:

s = "".join(func(c) for c in s)
Run Code Online (Sandbox Code Playgroud)

  • 小修正/点:一个仍然需要重新加入返回的列表(Py3 +中的/ iter/map-obj).所以上面应该是:`s ="".join(map(func,s))` (3认同)

Mic*_*ipp 5

该问题首先指出字符串是不可变的,然后要求找到一种方法来更改它们。这有点矛盾。无论如何,当您搜索“python 字符串就地修改”时,这个问题会出现在列表顶部,因此我将添加真正就地更改的答案。

当您查看字符串类的方法时,字符串似乎是不可变的。但没有一种具有 C 接口的语言能够真正提供不可变的数据类型。唯一的问题是您是否必须编写C 代码才能实现所需的修改。

在这里,Pythonctypes是你的朋友。由于它支持获取指针并包含类似 C 的内存复制函数,因此可以像这样就地修改python 字符串:

s = 16 * "."
print s
ctypes.memmove(ctypes.c_char_p(s), "Replacement", 11)
print s
Run Code Online (Sandbox Code Playgroud)

结果是:

................
Replacement.....
Run Code Online (Sandbox Code Playgroud)

(当然,您可以通过F对原始字符串的每个字符应用函数来在运行时计算替换字符串。前面的答案中已显示了执行此操作的不同方法。)

请注意,我不以任何方式鼓励这样做。但是,我必须编写一个从 C++ 映射到 python 的类的替代品,并包含一个方法:

int readData(char* data, int length)
Run Code Online (Sandbox Code Playgroud)

(调用者应该提供带有length字节的内存,然后该方法将可用数据写入length该内存,返回写入的字节数。)虽然这是 C/C++ 中的一个完全合理的 API,但它应该还没有作为 python 类的方法提供,或者至少应该让 API 的用户知道他们只能传递可变字节数组作为参数。

正如您所期望的,该方法的“常见用法”如我的示例所示(创建一个字符串并将其及其长度作为参数传递)。由于我并不是真的想编写 C/C++ 扩展,因此我必须想出一个仅使用 python 在替换类中实现行为的解决方案。


jat*_*ism 2

字符串是可迭代的,并且可以像列表一样遍历。字符串还具有许多基本方法,例如.replace()您可能正在寻找的方法。所有字符串方法都返回一个新字符串。因此,您可以简单地替换其现有值,而不是就地修改字符串。

>>> mystring = 'robot drama'
>>> mystring = mystring.replace('r', 'g')
>>> mystring
'gobot dgama'
Run Code Online (Sandbox Code Playgroud)