在别的论坛上看见:“你 python for loop 还 string += “a”,这一下子就暴露不科班了。” 这个说法。
在别的论坛上看见:“你 python for loop 还 string += “a”,这一下子就暴露不科班了。” 这个说法。
|
gwy15Jul 30, 2020
1
py str 不可变,如果要拼接字符串,类似 java 的 sb,用 List[str] 再 join 。
|
|
sagaxuJul 30, 2020 via Android
2
随便什么语言这么写都慢
|
|
ProcumbensJul 30, 2020
3
@sagaxu C++不慢
|
|
sagaxuJul 30, 2020 via Android
4
@Procumbens C++也慢,这种写法不能提前分配好长度合适的内存
|
|
realityoneJul 30, 2020
5
|
|
HstarJul 30, 2020
6
是 for loop 结合 string += 'a' 在 python 中慢
假设目前 string 为 "aa"内存地址是 a1,在一次+=之后会生成一个新的字符串对象 "aaa" 存在 a2 并将 string 指向 a2 所以 for loop 套 += 字符串操作会产生 N 个字符串对象的创建操作,效率较慢 |
|
deorthJul 30, 2020
7
所以说怎样写才快
|
|
9
反对这种写个 += 就暴露什么科班不科班。。
过早优化乃万恶之源 |
|
JeffGeJul 30, 2020 via Android
10
@realityone 我看这里面写的是 Python 2
|
|
CallMeReznovJul 30, 2020
11
所以说怎样写才快?
|
|
cs7Jul 30, 2020 via iPhone
12
我寻思搜索引擎是不好用吗 这种问题
|
|
djFFFFFJul 30, 2020
13
这不一定是说效率低吧,python 语法糖比较多,for loop 三四行的代码很多时候 list comprehension 一行代码就搞定了
|
|
binbinyouliiiiJul 30, 2020 via Android
14
正式项目不能这么写,自己为了 debug 随便你
|
|
marcong95Jul 30, 2020
15
所以所谓的科班就要先 malloc 再 strcat 么(手动滑稽)
我寻思着 string.join 也不怎么科班吧?可能我上课没听课(++手动滑稽) |
|
16
python 本身就效率很低,就不用追求这么细了吧
|
|
VegetableJul 30, 2020
17
https://gist.github.com/luliangce/f33d175e5a53db83ee2d2af91d3711be
这和循环的规模有很明显的关系。 单个循环次数比较小时,直接拼接效果更好,循环次数达到一定量级之后使用列表才有意义,这个量级我测试大概在 1000 左右,而且持续提高规模并不会明显提高差距。 楼上给的测试链接看起来,并不是很具有代表意义。 |
|
Trim21Jul 30, 2020
18
正经项目拼接字符串都是用 StringIO 的吗
|
|
iyaozhenJul 30, 2020
19
2.6 好像就有优化过了,你可以试试,实际不慢(或者没那么夸张)
该用还是用,一般循环次数也是有限,肯定不是性能问题的大头,甚至末尾都算不上 |
|
misaka19000Jul 30, 2020
20
反编译看一下字节码不就知道了
|
|
yangyaofeiJul 30, 2020
21
都用 Python 了,还在乎那点性能损失么...
真的在乎性能就不会用 python 吧,或者多线程多进程比这个性能提升多多了. |
|
JCZ2MkKb5S8ZX9pqJul 30, 2020
22
python cook book 好像有提过这个
但以我平时写的那些小破代码来说,可读性和直观程度更加重要一些。优不优化区别不大,真搞到需要优化了,我应该也能有预算找人帮我整个重构了。 |
|
goodrybJul 30, 2020
23
所以比较牛逼的写法应该是什么样子的,都用 python 了不是更应该注重开发效率吗
|
|
changweiJul 30, 2020
24
我很好奇编译器能不能自动识别出这种大量+=的语句,然后底层自动转换成 stringBuffer 来拼接?就像 c 或者 java 的 for 循环里面可以把 i++优化成++i 一样,我觉得这种比较有规律并且很普遍的写法在编译器上可以考虑一下特殊优化了。
|
|
a132811Jul 30, 2020
25
几乎没有差别, 时间都是随着 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
纠结这个能省几秒啊,不应该是写得差不多了再来查哪里是性能瓶颈然后针对优化么
|
|
wittyfansJul 30, 2020 via iPhone
27
在 stack overflow 上也看到了这个问题,可以看看。
https://stackoverflow.com/questions/39675898/is-python-string-concatenation-bad-practice 不科班的说法只能说明这人有点自以为是。 |
|
lbp0200Jul 30, 2020
28
想要性能,首先抛弃 Python,改用 C
|
|
caviarJul 30, 2020
29
个人感觉说这话的人也不是特别的科班。
确实 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 之类的为好。 |
|
caviarJul 30, 2020
30
呃... wtf-python 我是很早之前读的,好像记错了,那一段并没有详细讲这件事....
|
|
cyspyJul 30, 2020 via Android
31
难道 for +=比 join 易懂吗?
|
|
nuttingJul 30, 2020
32
一条语句没什么吧,循环里才值得商榷
|
|
acumenJul 30, 2020
33
任何抛开场景的讨论都是耍流氓(手动狗头
|
|
AlohaV2Jul 30, 2020
36
科班不科班都可以这样写,这么写可读性挺好的。
要不要这样写取决于你这行代码在整个程序里运行几遍(换句话说性能分析出来占多少的执行时间比例)。 |
|
matrix1010Jul 30, 2020
37
|
|
38
所以如果要避免的话,就用''.join() ?
|
|
AcooldaJul 31, 2020 via Android
39
别听那些沙雕文章忽悠,实用易懂是关键。
|
|
julyclydeJul 31, 2020
40
如果效率有问题那是语言自己没做好自己的工作
|
|
zxCoderJul 31, 2020
41
所以应该怎么写呢?上面这么多回复好像都没提到过
|