更改字符串中的一个字符?

kos*_*tia 345 python string

Python中替换字符串中字符的最简单方法是:

text = "abcdefg";
text[1] = "Z";
           ^
Run Code Online (Sandbox Code Playgroud)

scv*_*lex 486

不要修改字符串.

与他们一起作为名单; 只在需要时将它们变成字符串.

>>> s = list("Hello zorld")
>>> s
['H', 'e', 'l', 'l', 'o', ' ', 'z', 'o', 'r', 'l', 'd']
>>> s[6] = 'W'
>>> s
['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']
>>> "".join(s)
'Hello World'
Run Code Online (Sandbox Code Playgroud)

Python字符串是不可变的(即它们不能被修改).这有很多原因.使用列表直到您别无选择,只有将它们转换为字符串.

  • 答案中的链接已失效。 (7认同)
  • 那些寻求速度/效率的人,[阅读本文](http://stackoverflow.com/a/22149018/4334743) (4认同)
  • "不要修改字符串." 为什么 (3认同)
  • “创建->修改->序列化->分配->自由”比s[6]='W'更有效?嗯...为什么其他语言允许它,尽管有“很多”的原因?有趣的是如何保护一个奇怪的设计(我想是为了爱)。为什么不建议将函数 MID(strVar,index,newChar) 添加到直接访问 char 内存位置的 Python 核心,而不是对整个字符串进行不必要的字节洗牌? (3认同)
  • @hacksoi,@oscar,原因很简单:在传递指针时不需要重新计数来实现修改时复制,或者直接复制整个字符串以防有人想要修改该字符串 - 这会导致泛型的速度提高使用。由于切片,不需要像“MID”这样的东西:“s[:index] + c + s[index+1:]” (3认同)
  • @oscar这并不是因为“奇怪的设计”,而是因为Python区分unicode和字节字符串,这很好,因为“哑”语言的用户往往会忽略不同编码的存在,这会导致很多问题以后的麻烦。 (2认同)
  • @oscar 我所说的“愚蠢的语言”是指它们不处理 unicode,除非你明确告诉它们这样做。当然,您可以用 C 语言编写支持 unicode 的应用程序。但是您必须始终关心它,并且需要显式地测试它以避免出现麻烦。一切都是以机器为导向的。在学习 Python 之前,我使用过 PHP,该语言一团糟。关于您关于快速 CPU 的评论,我完全同意您的观点。但这个问题的一部分是人们普遍反对过早优化,这会导致解释器和库的速度变慢,从而泄漏大量 CPU 周期。 (2认同)
  • @oscar,是的,Python 中的字符串是不可变的,所以你必须保留一个新的内存块,并在任何情况下复制你需要的所有数据。但你并没有像你声称的那样浪费了那么多周期。大多数用例不需要您修改字符串,但它确实需要您大量传递字符串,因此拥有不可变字符串确实是合理的。如果您需要改变其内容,您可以使用其他数据结构,如果您喜欢的话,还有其他更接近金属的语言。 (2认同)

Meh*_*len 170

最快的方法?

有三种方法.对于速度寻求者,我建议'方法2'

方法1

由这个答案给出

text = 'abcdefg'
new = list(text)
new[6] = 'W'
''.join(new)
Run Code Online (Sandbox Code Playgroud)

与"方法2"相比,这相当慢

timeit.timeit("text = 'abcdefg'; s = list(text); s[6] = 'W'; ''.join(s)", number=1000000)
1.0411581993103027
Run Code Online (Sandbox Code Playgroud)

方法2(快速方法)

由这个答案给出

text = 'abcdefg'
text = text[:1] + 'Z' + text[2:]
Run Code Online (Sandbox Code Playgroud)

哪个更快:

timeit.timeit("text = 'abcdefg'; text = text[:1] + 'Z' + text[2:]", number=1000000)
0.34651994705200195
Run Code Online (Sandbox Code Playgroud)

方法3:

字节数组:

timeit.timeit("text = 'abcdefg'; s = bytearray(text); s[1] = 'Z'; str(s)", number=1000000)
1.0387420654296875
Run Code Online (Sandbox Code Playgroud)

  • 看看它与 bytearray 方法相比如何,也会很有趣。 (3认同)
  • 好建议。bytearray 方法也较慢: `timeit.timeit("text = 'abcdefg'; s = bytearray(text); s[1] = 'Z'; str(s)", number=1000000)` 慢两倍最快的一个。 (3认同)
  • 需要注意的是,这里大部分时间都花在转换上...(字符串 -> 字节数组)。如果要对字符串进行多次编辑,那么字节数组方法会更快。 (3认同)
  • 欣赏测试,这让我重新思考如何操作Python字符串. (2认同)
  • 好的。请编辑答案以也包括方法 3 (bytearray)。 (2认同)
  • 方法 3 不适用于包含非 ASCII 字符(字符/字节值大于 127)的 UTF8 字符串,Char 的 b/c 分配以超过 1 个字节进行编码。 (2认同)

Joc*_*zel 124

new = text[:1] + 'Z' + text[2:]
Run Code Online (Sandbox Code Playgroud)

  • @Ooker 在 StackExchange 上引用“下面”的答案是一件危险的事情;) (3认同)
  • 如果你不明白为什么会这样,[见下面的答案](http://stackoverflow.com/a/1228327/3416774) (2认同)

Mar*_*ett 33

Python字符串是不可变的,您可以通过制作副本来更改它们.
做你想做的最简单的方法可能就是.

text = "Z" + text[1:]
Run Code Online (Sandbox Code Playgroud)

文本[1:]将文本中的字符串从位置1返回到结尾,位置计数从0开始,因此"1"是第二个字符.

编辑:您可以对字符串的任何部分使用相同的字符串切片技术

text = text[:1] + "Z" + text[2:]
Run Code Online (Sandbox Code Playgroud)

或者,如果只出现一次字母,您可以使用下面建议的搜索和替换技术


Mah*_*oud 13

从python 2.6和python 3开始,你可以使用可变的bytearrays(可以像字符串一样改变字符串):

s = "abcdefg"
b_s = bytearray(s)
b_s[1] = "Z"
s = str(b_s)
print s
aZcdefg
Run Code Online (Sandbox Code Playgroud)

编辑:将str更改为s

edit2:作为评论中提到的Two-Bit Alchemist,此代码不适用于unicode.

  • 这个答案是不正确的。一方面,它应该是“bytearray(s)”,而不是“bytearray(str)”。另一方面,这将产生:“TypeError:没有编码的字符串参数”。如果指定编码,则会收到“TypeError:需要整数”。这是Python 3 或Python 2 的unicode。如果您在 Python 2 中执行此操作(使用更正的第二行),则它不适用于非 ASCII 字符,因为它们可能不仅仅是一个字节。尝试使用`s = 'Héllo'`,您将得到“He\xa9llo”。 (2认同)
  • 不要这样做。此方法忽略了字符串编码的整个概念,这意味着它仅适用于ASCII字符。在当今时代,即使您是英语国家的英语使用者,也无法假定ASCII。Python3最大的后向不兼容(我认为最重要)是修复整个字节=字符串错误的等效性。不要带回来。 (2认同)

小智 8

这段代码不是我的。我不记得网站表格在哪里,我拿了它。有趣的是,您可以使用它用一个或多个字符替换一个或多个字符。虽然这个回复很晚,但像我这样的新手(任何时候)可能会觉得它很有用。

更改文本功能。

mytext = 'Hello Zorld'
mytext = mytext.replace('Z', 'W')
print mytext,
Run Code Online (Sandbox Code Playgroud)

  • 这不能回答问题。这根本不是我们想要的。 (11认同)
  • @Ooker 如果你想替换 _only_ 第一个字符,你可以使用 `mytext = mytext.replace('l', 'W',1)`。[文档链接](https://www.tutorialspoint.com/python/string_replace.htm) (4认同)
  • @ProfVersaggi 这绝对是错误的。请参阅上面 Oooker 的评论。 (3认同)
  • 如果您只想替换*第一个`l`,则此代码很糟糕。`mytext = mytext.replace('l', 'W')` -> `HeWWo Zorld` (2认同)

Unk*_*own 7

就像其他人所说的那样,通常 Python 字符串应该是不可变的。

但是,如果您使用 CPython(python.org 上的实现),则可以使用 ctypes 来修改内存中的字符串结构。

这是我使用该技术清除字符串的示例。

在python中将数据标记为敏感

为了完整起见,我提到了这一点,这应该是您的最后手段,因为它是骇人听闻的。

  • 最后一招?如果你*曾经*这样做,你会突然被贴上邪恶的烙印! (7认同)
  • @Cabu我*永远不会*在*任何*情况下接受这样做的代码。如果您的数据很敏感并且您像这样关心安全性,那么 *`str` 不是适合您的类型。* 只是不要使用它。请改用“bytearray”之类的东西。(更好的是,将其包装在某种东西中,让您或多或少将其视为不透明数据,这样您就真的“无法”从中检索“str”,以保护您免受事故的影响。可能有一个库可以做到这一点。 不知道。) (2认同)

Man*_*r S 6

字符串在 Python 中是不可变的,这意味着您不能更改现有字符串。但是如果你想改变其中的任何字符,你可以创建一个新的字符串,如下所示,

def replace(s, position, character):
    return s[:position] + character + s[position+1:]
Run Code Online (Sandbox Code Playgroud)

replace('King', 1, 'o')
// 结果:Kong

注意:如果你给的位置值大于字符串的长度,它会在末尾追加字符。

replace('Dog', 10, 's')
// 结果:Dogs


Oso*_*oSP 6

我喜欢 F 弦:

text = f'{text[:1]}Z{text[2:]}'
Run Code Online (Sandbox Code Playgroud)

在我的机器上,这个方法比使用 + 连接字符串的“快速方法”快 10%:

>>> timeit.timeit("text = 'abcdefg'; text = text[:1] + 'Z' + text[2:]", number=1000000)
1.1691178000000093
>>> timeit.timeit("text = 'abcdefg'; text = f'{text[:1]}Z{text[2:]}'", number =1000000)
0.9047831999999971
>>>
Run Code Online (Sandbox Code Playgroud)

  • 这是一个有趣的方法。请考虑使用 Markdown 格式化内联代码并发布有关您的基准测试和测试的详细信息。 (2认同)