我正在使用实现__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对象提供支持有点尴尬.
请注意以下所有:
与添加形成一个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如果您觉得它会有所帮助.
| 归档时间: |
|
| 查看次数: |
1206 次 |
| 最近记录: |