在别的论坛上看见:“你 python for loop 还 string += “a”,这一下子就暴露不科班了。” 这个说法。
1
gwy15 2020-07-30 13:08:25 +08:00
py str 不可变,如果要拼接字符串,类似 java 的 sb,用 List[str] 再 join 。
|
2
sagaxu 2020-07-30 13:09:48 +08:00 via Android
随便什么语言这么写都慢
|
3
Procumbens 2020-07-30 13:10:16 +08:00
@sagaxu C++不慢
|
4
sagaxu 2020-07-30 13:12:10 +08:00 via Android
@Procumbens C++也慢,这种写法不能提前分配好长度合适的内存
|
5
realityone 2020-07-30 13:14:41 +08:00
|
6
Hstar 2020-07-30 13:19:38 +08:00
是 for loop 结合 string += 'a' 在 python 中慢
假设目前 string 为 "aa"内存地址是 a1,在一次+=之后会生成一个新的字符串对象 "aaa" 存在 a2 并将 string 指向 a2 所以 for loop 套 += 字符串操作会产生 N 个字符串对象的创建操作,效率较慢 |
7
deorth 2020-07-30 13:23:55 +08:00
所以说怎样写才快
|
9
STRRL 2020-07-30 13:32:10 +08:00 via Android 7
反对这种写个 += 就暴露什么科班不科班。。
过早优化乃万恶之源 |
10
JeffGe 2020-07-30 13:37:24 +08:00 via Android
@realityone 我看这里面写的是 Python 2
|
11
CallMeReznov 2020-07-30 13:43:50 +08:00
所以说怎样写才快?
|
12
heygum97 2020-07-30 13:49:09 +08:00 via iPhone
我寻思搜索引擎是不好用吗 这种问题
|
13
djFFFFF 2020-07-30 13:53:09 +08:00
这不一定是说效率低吧,python 语法糖比较多,for loop 三四行的代码很多时候 list comprehension 一行代码就搞定了
|
14
binbinyouliiii 2020-07-30 13:53:13 +08:00 via Android
正式项目不能这么写,自己为了 debug 随便你
|
15
marcong95 2020-07-30 13:53:38 +08:00
所以所谓的科班就要先 malloc 再 strcat 么(手动滑稽)
我寻思着 string.join 也不怎么科班吧?可能我上课没听课(++手动滑稽) |
16
love 2020-07-30 13:56:41 +08:00 1
python 本身就效率很低,就不用追求这么细了吧
|
17
Vegetable 2020-07-30 14:09:23 +08:00
https://gist.github.com/luliangce/f33d175e5a53db83ee2d2af91d3711be
这和循环的规模有很明显的关系。 单个循环次数比较小时,直接拼接效果更好,循环次数达到一定量级之后使用列表才有意义,这个量级我测试大概在 1000 左右,而且持续提高规模并不会明显提高差距。 楼上给的测试链接看起来,并不是很具有代表意义。 |
18
Trim21 2020-07-30 14:12:08 +08:00
正经项目拼接字符串都是用 StringIO 的吗
|
19
iyaozhen 2020-07-30 14:43:59 +08:00
2.6 好像就有优化过了,你可以试试,实际不慢(或者没那么夸张)
该用还是用,一般循环次数也是有限,肯定不是性能问题的大头,甚至末尾都算不上 |
20
misaka19000 2020-07-30 14:53:08 +08:00
反编译看一下字节码不就知道了
|
21
yangyaofei 2020-07-30 14:58:11 +08:00
都用 Python 了,还在乎那点性能损失么...
真的在乎性能就不会用 python 吧,或者多线程多进程比这个性能提升多多了. |
22
JCZ2MkKb5S8ZX9pq 2020-07-30 14:58:19 +08:00
python cook book 好像有提过这个
但以我平时写的那些小破代码来说,可读性和直观程度更加重要一些。优不优化区别不大,真搞到需要优化了,我应该也能有预算找人帮我整个重构了。 |
23
goodryb 2020-07-30 15:12:04 +08:00
所以比较牛逼的写法应该是什么样子的,都用 python 了不是更应该注重开发效率吗
|
24
changwei 2020-07-30 15:54:24 +08:00
我很好奇编译器能不能自动识别出这种大量+=的语句,然后底层自动转换成 stringBuffer 来拼接?就像 c 或者 java 的 for 循环里面可以把 i++优化成++i 一样,我觉得这种比较有规律并且很普遍的写法在编译器上可以考虑一下特殊优化了。
|
25
a132811 2020-07-30 17:06:35 +08:00
几乎没有差别, 时间都是随着 n 线性增长
```python >>> timeit.timeit('for i in range(int(1e8)):s+="a"', setup='s=""', number=1) 11.196388629000012 >> timeit.timeit('for i in range(int(1e8)):s.write("s")', setup='from io import StringIO; s=StringIO()', number=1) 8.931465667999987 >>> timeit.timeit('"".join(["a" for i in range(int(1e8))])', setup='from io import StringIO; s=StringIO()', number=1) 4.056428481000012 ``` |
26
MinQ 2020-07-30 17:09:35 +08:00 1
纠结这个能省几秒啊,不应该是写得差不多了再来查哪里是性能瓶颈然后针对优化么
|
27
wittyfans 2020-07-30 17:19:19 +08:00 via iPhone
在 stack overflow 上也看到了这个问题,可以看看。
https://stackoverflow.com/questions/39675898/is-python-string-concatenation-bad-practice 不科班的说法只能说明这人有点自以为是。 |
28
lbp0200 2020-07-30 17:21:51 +08:00
想要性能,首先抛弃 Python,改用 C
|
29
caviar 2020-07-30 17:30:32 +08:00
个人感觉说这话的人也不是特别的科班。
确实 python 的 str 是 immutable 的,所以理论上 for loop 中 使用 string += "a" 的复杂度非常恐怖,尤其是在 string 很长的情况下,毕竟每次都要完整复制一份。 但是实际上因为这个 case 太常见了,CPython 很早就有这个优化。即,如果这个 string 没有别的 reference ( non-alised )的时候,会直接 destructive update (官方的叫法是 in-place string concatenation )。因此从某种角度上说,python 的 str 可能会是 mutable 的,类似 list,每次创建时增长一下预留的空间。详细的说明可以看 wtf-python 里的 let's make a giant string https://github.com/satwikkansal/wtfpython#-lets-make-a-giant-string 当然如果场景合适或数量非常大甚至是瓶颈的话,还是用 join 之类的为好。 |
30
caviar 2020-07-30 17:41:14 +08:00
呃... wtf-python 我是很早之前读的,好像记错了,那一段并没有详细讲这件事....
|
31
cyspy 2020-07-30 17:48:50 +08:00 via Android
难道 for +=比 join 易懂吗?
|
32
nutting 2020-07-30 18:05:54 +08:00
一条语句没什么吧,循环里才值得商榷
|
33
acumen 2020-07-30 19:22:26 +08:00
任何抛开场景的讨论都是耍流氓(手动狗头
|
36
AlohaV2 2020-07-30 19:30:47 +08:00
科班不科班都可以这样写,这么写可读性挺好的。
要不要这样写取决于你这行代码在整个程序里运行几遍(换句话说性能分析出来占多少的执行时间比例)。 |
37
matrix1010 2020-07-30 22:09:18 +08:00
|
38
Alpacino OP 所以如果要避免的话,就用''.join() ?
|
39
Acoolda 2020-07-31 10:03:35 +08:00 via Android
别听那些沙雕文章忽悠,实用易懂是关键。
|
40
julyclyde 2020-07-31 16:42:01 +08:00
如果效率有问题那是语言自己没做好自己的工作
|
41
zxCoder 2020-07-31 20:00:16 +08:00
所以应该怎么写呢?上面这么多回复好像都没提到过
|