Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
避免Python sum默认启动参数行为_Python_Sum - Fatal编程技术网

避免Python sum默认启动参数行为

避免Python sum默认启动参数行为,python,sum,Python,Sum,我正在使用一个Python对象,它实现了\uuuuu add\uuuuu,但没有子类intMyObj1+MyObj2工作正常,但是sum([MyObj1,MyObj2])导致了类型错误,因为sum()第一次尝试0+MyObj。为了使用sum(),我的对象需要处理MyObj+0或我需要提供一个空对象作为开始参数。所讨论的对象不是设计为空的 在任何人询问之前,对象不是类似列表或字符串的,因此使用join()或itertools不会有帮助 编辑以获取详细信息:模块有一个SimpleLocation和一

我正在使用一个Python对象,它实现了
\uuuuu add\uuuuu
,但没有子类
int
MyObj1+MyObj2
工作正常,但是
sum([MyObj1,MyObj2])
导致了
类型错误
,因为
sum()
第一次尝试
0+MyObj
。为了使用
sum()
,我的对象需要
处理
MyObj+0
我需要提供一个空对象作为
开始
参数。所讨论的对象不是设计为空的

在任何人询问之前,对象不是类似列表或字符串的,因此使用join()或itertools不会有帮助

编辑以获取详细信息:模块有一个SimpleLocation和一个CompoundLocation。我将把地点缩写为Loc。
SimpleLoc
包含一个右开区间,即[start,end]。添加
SimpleLoc
将生成一个
CompoundLoc
,其中包含区间列表,例如
[[3,6],[10,13)]
。最终使用包括通过联合进行迭代,例如
[3,4,5,10,11,12]
,检查长度和成员资格

数字可以相对较大(例如,小于2^32,但通常为2^20)。间隔可能不会很长(100-2000,但可能更长)。目前,只存储端点。我现在暂时考虑尝试将
set
子类化,以便将位置构造为
set(xrange(start,end))
。但是,添加集合将使Python(和数学家)适合

我看到的问题有:

我正在考虑两种解决方案。一种是避免
sum()
并使用本文提供的循环。我不明白为什么
sum()
首先将iterable的第0项添加到0,而不是添加第0项和第1项(如链接注释中的循环);我希望这是一个神秘的整数优化原因

我的另一个解决方案如下;虽然我不喜欢硬编码的零检查,但这是我唯一能够使
sum()
工作的方法

# ...
def __radd__(self, other):
    # This allows sum() to work (the default start value is zero)
    if other == 0:
        return self
    return self.__add__(other)

总之,对于既不能添加到整数也不能为空的对象,是否有另一种方法使用
sum()
呢?

我认为实现这一点的最佳方法是提供
\u radd\u
方法,或者将start对象显式传递给sum

如果您确实不想覆盖
\uuu radd\uuu
或提供一个开始对象,那么重新定义
sum()
怎么样


最好使用名为my_sum()
的函数,但我想这是您想要避免的事情之一(即使全局重新定义内置函数可能是未来的维护人员会诅咒您的事情)

实际上,实现
\uuuu add\uu
时没有“空对象”的概念没有什么意义。
sum
需要一个
start
参数来支持空序列和单元素序列的总和,并且您必须决定在这些情况下预期的结果:

sum([o1, o2]) => o1 + o2  # obviously
sum([o1]) => o1  # But how should __add__ be called here?  Not at all?
sum([]) => ?  # What now?

不要使用
sum
,而是使用:

import operator
from functools import reduce
reduce(operator.add, seq)
Python 2中内置了
reduce
,因此如下所示:

import operator
reduce(operator.add, seq)
Reduce通常比sum更灵活-您可以提供任何二进制函数,不仅是
add
,还可以选择提供初始元素,而
sum
始终使用一个


另请注意:(警告:前面有数学咆哮)

从代数的角度来看,为没有中性元素的w/r/t对象提供
add
w/r/t支持有点笨拙

请注意:

  • 自然的
  • 雷亚尔
  • 复数
  • N-d向量
  • NxM矩阵
与加法形式a-一起,即它们是结合的,具有某种中性元素

如果您的操作是非关联的,并且没有中性元素,那么它就不会“类似”加法。因此,不要指望它能与
sum
一起很好地工作

在这种情况下,您最好使用函数或方法而不是运算符。这可能会减少混淆,因为您的类的用户看到它支持
+
,可能会期望它将以单向方式运行(就像加法通常所做的那样)


感谢您的扩展,我现在将参考您的特定模块:

这里有两个概念:

  • 位置简单
  • 大院的位置
简单的位置可以被添加是有意义的,但它们不能形成幺半群,因为它们的添加不满足闭包的基本性质——两个SimpleLoc的和不是SimpleLoc,通常是CompoundLoc

OTOH,对我来说,带加法的复合群看起来像一个幺半群(一个交换幺半群,当我们在这里的时候):它们的和也是一个复合群,它们的加法是结合的,交换的,中性元素是一个空的复合群,包含零个simpleLoc。

如果您同意我的意见(并且上述内容与您的实现相匹配),那么您将能够使用
sum
,如下所示:

sum( [SimpleLoc1, SimpleLoc2, SimpleLoc3], start=ComplexLoc() )
事实上,这一点很重要


我现在暂时考虑尝试对set进行子类化,以便将位置构造为set(xrange(start,end))。但是,添加set将使Python(和数学家)适合

嗯,位置是一些数字集,因此在它们上面抛出一个类似集合的接口是有意义的(因此
\uuuuu包含
\uuuuu iter\uuuuu
\uuu len\uuuuu
,可能
\uuuuu或
作为
+/code>的别名,
\uuuu和
作为产品,等等)

至于从
xrange
构造,你真的需要它吗?如果你知道你正在存储区间集,那么你可能会通过坚持使用
[开始,结束)
对来节省空间
sum( [SimpleLoc1, SimpleLoc2, SimpleLoc3], start=ComplexLoc() )
from operator import add
try:
    total = reduce(add, whatever) # or functools.reduce in Py3.x
except TypeError as e:
    # I'm not 100% happy about branching on the exception text, but
    # figure this msg isn't likely to be changed after so long...
    if e.args[0] == 'reduce() of empty sequence with no initial value':
        pass # do something appropriate here if necessary
    else:
        pass # Most likely that + isn't usable between objects...
class Neutral:
    def __add__(self, other):
        return other

print(sum("A BC D EFG".split(), Neutral())) # ABCDEFG