避免Python和默认启动arg行为

Len*_*nna 14 python sum

我正在使用实现__add__但不是子类的Python对象int.MyObj1 + MyObj2工作正常,但sum([MyObj1, MyObj2])导致了TypeError,因为sum()第一次尝试0 + MyObj.为了使用sum(),我的对象需要__radd__处理MyObj + 0 或者我需要提供一个空对象作为start参数.有问题的对象不是空的.

在有人要求之前,该对象不像列表或类似字符串,因此使用join()或itertools无济于事.

编辑以获取详细信息:模块具有SimpleLocation和CompoundLocation.我将把位置缩写为Loc.A SimpleLoc包含一个右开间隔,即[开始,结束].添加SimpleLoc产量a 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)
Run Code Online (Sandbox Code Playgroud)

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

Kos*_*Kos 12

而不是sum,使用:

import operator
from functools import reduce
reduce(operator.add, seq)
Run Code Online (Sandbox Code Playgroud)

在Python 2中reduce是内置的,所以这看起来像:

import operator
reduce(operator.add, seq)
Run Code Online (Sandbox Code Playgroud)

Reduce通常比sum更灵活 - 您不仅可以提供任何二进制函数add,而且您可以选择提供初始元素,同时sum始终使用一个元素.


还要注意:( 警告:数学前进)

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

请注意以下所有:

  • 土黄
  • 雷亚尔
  • 复数
  • Nd向量
  • NxM矩阵
  • 字符串

与添加形成一个Monoid - 即它们是关联的并且具有某种中性元素.

如果您的操作不是关联的并且没有中性元素,那么它不会"类似"添加.因此,不要指望它能够很好地发挥作用sum.

在这种情况下,使用函数或方法而不是运算符可能会更好.这可能不那么令人困惑,因为你的类的用户看到它支持+,可能会期望它会以一种单调的方式运行(正如加法通常那样).


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

这里有两个概念:

  • 简单的位置,
  • 复合位置.

确实可以添加简单的位置,但它们不会形成一个monoid,因为它们的加法不满足闭包的基本属性 - 两个SimpleLocs的总和不是SimpleLoc.通常,它是一个CompoundLoc.

OTOH,与另外CompoundLocs看起来像一个幺给我(可交换的独异,而我们在这):这些的总和为一个CompoundLoc过了,它们的加入为联想,交换和中性元素是包含一个空CompoundLoc零SimpleLocs.

如果您同意我(以及上述内容与您的实施相符),那么您将能够使用sum如下:

sum( [SimpleLoc1, SimpleLoc2, SimpleLoc3], start=ComplexLoc() )
Run Code Online (Sandbox Code Playgroud)

实际上,这似乎有效.


我现在暂时想到尝试子集set,使得该位置被构造为set(xrange(start,end)).但是,添加集将使Python(和数学家)适合.

好了,位置是一些组数字,因此是很有意义扔在他们之上的一套类似的界面(所以__contains__,__iter__,__len__,也许__or__作为一个别名+,__and__作为产品等).

至于建筑xrange,你真的需要吗?如果你知道你正在存储间隔集,那么你可能会通过坚持你的[start, end)对的表示来节省空间.您可以引入一个实用程序方法,该方法采用任意整数序列并将其转换为最佳值,SimpleLoc或者CompoundLoc如果您觉得它会有所帮助.