Muh*_*uri 61 python types sum built-in
Python有一个内置函数sum,它实际上相当于:
def sum2(iterable, start=0):
return start + reduce(operator.add, iterable)
Run Code Online (Sandbox Code Playgroud)
除了字符串之外的所有类型的参数.它适用于数字和列表,例如:
sum([1,2,3], 0) = sum2([1,2,3],0) = 6 #Note: 0 is the default value for start, but I include it for clarity
sum({888:1}, 0) = sum2({888:1},0) = 888
Run Code Online (Sandbox Code Playgroud)
为什么特别遗漏了字符串?
sum( ['foo','bar'], '') # TypeError: sum() can't sum strings [use ''.join(seq) instead]
sum2(['foo','bar'], '') = 'foobar'
Run Code Online (Sandbox Code Playgroud)
我似乎记得在Python列表中讨论的原因,所以解释或解释它的线程的链接会很好.
编辑:我知道标准的方法是做"".join.我的问题是为什么禁止对字符串使用sum的选项,并且没有禁止,例如,列表.
编辑2:虽然我认为这不是必需的,但我得到了所有的好答案,问题是:为什么sum在包含数字的迭代或包含列表的迭代但不包含包含字符串的迭代?
rbp*_*rbp 49
Python试图阻止你"汇总"字符串.你应该加入他们:
"".join(list_of_strings)
Run Code Online (Sandbox Code Playgroud)
它的速度要快得多,并且使用的内存要少得多.
快速基准:
$ python -m timeit -s 'import operator; strings = ["a"]*10000' 'r = reduce(operator.add, strings)'
100 loops, best of 3: 8.46 msec per loop
$ python -m timeit -s 'import operator; strings = ["a"]*10000' 'r = "".join(strings)'
1000 loops, best of 3: 296 usec per loop
Run Code Online (Sandbox Code Playgroud)
编辑(回答OP的编辑):至于为什么字符串显然被"挑出",我认为这只是优化常见案例,以及强制执行最佳实践的问题:你可以用''更快地加入字符串.加入,所以明确禁止字符串sum将指向新手.
顺便说一句,这种限制已经"永远"存在,即,因为它sum被添加为内置函数(rev.32347)
u0b*_*6ae 27
实际上sum(..),如果使用适当的起始对象,您可以使用连接字符串!当然,如果你走到这一步,你已经理解了足够的使用"".join(..)..
>>> class ZeroObject(object):
... def __add__(self, other):
... return other
...
>>> sum(["hi", "there"], ZeroObject())
'hithere'
Run Code Online (Sandbox Code Playgroud)
HS.*_*HS. 17
这是源代码:http://svn.python.org/view/python/trunk/Python/bltinmodule.c ?revision = 81029&view = markup
在builtin_sum函数中,我们有这段代码:
/* reject string values for 'start' parameter */
if (PyObject_TypeCheck(result, &PyBaseString_Type)) {
PyErr_SetString(PyExc_TypeError,
"sum() can't sum strings [use ''.join(seq) instead]");
Py_DECREF(iter);
return NULL;
}
Py_INCREF(result);
}
Run Code Online (Sandbox Code Playgroud)
那么..这是你的答案.
它在代码中明确检查并被拒绝.
unu*_*tbu 14
来自文档:
连接字符串序列的首选快速方法是调用'.join(sequence).
通过sum拒绝对字符串进行操作,Python鼓励您使用正确的方法.
dan*_*n04 11
简短回答:效率.
答案很长:该sum函数必须为每个部分和创建一个对象.
假设创建对象所需的时间量与其数据的大小成正比.设N表示序列中要求求和的元素数.
doubles总是大小相同,这使得sum运行时间为O(1)×N = O(N).
int(以前称为long)是任意长度.设M表示最大序列元素的绝对值.那么sum最坏情况下的运行时间是lg(M)+ lg(2M)+ lg(3M)+ ... + lg(NM)= N×lg(M)+ lg(N!)= O(N log N).
对于str(其中M =最长字符串的长度),最坏情况下的运行时间是M + 2M + 3M + ... + NM = M×(1 + 2 + ... + N)= O(N²).
因此,summing字符串将比summing数字慢得多.
str.join不分配任何中间对象.它预分配一个足够大的缓冲区来保存连接的字符串,并复制字符串数据.它在O(N)时间运行,比它快得多sum.
Eth*_*man 10
之所以
@ dan04对使用sum大型字符串列表的成本有很好的解释.
关于为什么str不被允许的缺失部分是sum许多人试图sum用于字符串,并且没有多少sum用于列表和元组以及其他O(n**2)数据结构.该陷阱sum适用于短字符串列表,但随后可以投入生产,其中列表可能很大,并且性能会慢慢爬行.这是一个常见的陷阱,在此实例中决定忽略duck-typing,并且不允许使用字符串sum.