<p>虽然<code>str.replace</code>只能用另一个子字符串替换一个子字符串,但<code>re.sub</code>可以替换一个模式</p>
<pre><code>In [55]: eSToAvoid = 'éêèÉÊÈ'
In [58]: import re
</code></pre>
<p>测试用例:</p>
<pre><code>In [61]: re.sub(r'[éêèÉÊÈ]', 'e', 'foobar')
Out[61]: 'foobar'
In [62]: re.sub(r'[éêèÉÊÈ]', 'e', eSToAvoid)
Out[62]: 'eeeeee'
In [63]: re.sub(r'[éêèÉÊÈ]', 'e', 'testingè,É foobar è É')
Out[63]: 'testinge,e foobar e e'
</code></pre>
<p>字符串替换方法是:</p>
<pre><code>In [70]: astr = 'testingè,É foobar è É'
...: for e in eSToAvoid:
...: astr = astr.replace(e,'e')
...:
In [71]: astr
Out[71]: 'testinge,e foobar e e'
</code></pre>
<p>替换顺序应用于<code>astr</code>。这不能表示为列表理解(或<code>map</code>)。列表理解最自然地取代了在列表中收集其结果的循环(使用^{<cd5>)</p>
<p>for循环没有问题。它实际上更快:</p>
<pre><code>In [72]: %%timeit
...: astr = 'testingè,É foobar è É'
...: for e in eSToAvoid:
...: astr = astr.replace(e,'e')
...:
...:
1.37 µs ± 8.96 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [73]: timeit re.sub(r'[éêèÉÊÈ]', 'e', 'testingè,É foobar è É')
2.79 µs ± 15.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [77]: timeit astr.translate(str.maketrans(eSToAvoid, 'e' * len(eSToAvoid)))
2.56 µs ± 14.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
</code></pre>
<h2>减少</h2>
<pre><code>In [93]: from functools import reduce
In [96]: reduce(lambda s,e: s.replace(e,'e'),eSToAvoid, 'testingè,É foobar è É' )
Out[96]: 'testinge,e foobar e e'
In [97]: timeit reduce(lambda s,e: s.replace(e,'e'),eSToAvoid, 'testingè,É foobar è É' )
2.11 µs ± 32.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
</code></pre>
<p>为了好玩,您还可以探索此处介绍的一些想法:</p>
<p><a href="https://stackoverflow.com/questions/39688133/cleanest-way-to-combine-reduce-and-map-in-python">Cleanest way to combine reduce and map in Python</a></p>
<p>您想要“累积”更改,要做到这一点,您需要某种类型的累加器,即挂在最后一次替换上的累加器<code>itertools</code>有一个<code>accumulate</code>函数,py3.8引入了一个<code>:=</code>walrus操作符</p>
<h2>发电机</h2>
<pre><code>In [110]: def foo(astr, es):
...: for e in es:
...: astr = astr.replace(e,'e')
...: yield astr
...:
In [111]: list(foo(astr, eSToAvoid))
Out[111]:
['testingè,É foobar è É',
'testingè,É foobar è É',
'testinge,É foobar e É',
'testinge,e foobar e e',
'testinge,e foobar e e',
'testinge,e foobar e e']
</code></pre>
<p>或者<code>[s for s in foo(astr, eSToAvoid)]</code>代替<code>list()</code>。这突出了一个事实,即列表理解返回一个字符串列表,即使字符串累积了更改</p>