gpt4 book ai didi

python - 避免 Python sum 默认启动 arg 行为

转载 作者:太空狗 更新时间:2023-10-29 17:16:17 26 4
gpt4 key购买 nike

我正在使用一个 Python 对象,它实现了 __add__,但没有子类化 intMyObj1 + MyObj2 工作正常,但是 sum([MyObj1, MyObj2]) 导致了 TypeError,因为 sum() 首先尝试 0 + MyObj。为了使用sum(),我的对象需要__radd__来处理MyObj + 0或者我需要提供一个空对象作为 start 参数。所讨论的对象并非设计为空。

在任何人问之前,该对象既不是列表也不是字符串,因此使用 join() 或 itertools 无济于事。

编辑细节:该模块有一个 SimpleLocation 和一个 CompoundLocation。我将 Location 缩写为 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() 并使用此 comment 中提供的循环.我不明白为什么 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()

最佳答案

代替 sum,使用:

import operator
from functools import reduce
reduce(operator.add, seq)

在 Python 2 中,reduce 是内置的,因此看起来像这样:

import operator
reduce(operator.add, seq)

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


另请注意:(警告:前面有数学问题)

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

请注意所有:

  • 自然
  • 雷亚尔
  • 复数
  • N-d 向量
  • NxM 矩阵
  • 字符串

与加法一起形成一个Monoid - 即它们具有关联性并具有某种中性元素。

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

在这种情况下,使用函数或方法而不是运算符可能会更好。这可能不那么令人困惑,因为您的类的用户看到它支持 +,可能会期望它以幺半群的方式运行(就像加法通常那样)。


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

这里有2个概念:

  • 简单的位置,
  • 综合地点。

添加简单位置确实有意义,但它们不会形成幺半群,因为它们的添加不满足闭包的基本属性 - 两个 SimpleLoc 的总和不是 SimpleLoc。通常,它是一个 CompoundLoc。

OTOH,在我看来,带有加法的 CompoundLocs 就像一个幺半群(一个可交换的幺半群,而我们正在讨论它):它们的总和也是一个 CompoundLoc,它们的加法是结合的、交换的和中性元素是包含零个 SimpleLoc 的空 CompoundLoc。

如果你同意我的观点(并且以上符合你的实现),那么你将能够使用 sum 如下:

sum( [SimpleLoc1, SimpleLoc2, SimpleLoc3], start=ComplexLoc() )

的确,这个appears to work .


I am now tentatively thinking of attempting to subclass set such that the location is constructed as set(xrange(start, end)). However, adding sets will give Python (and mathematicians) fits.

好吧,位置是一些数字集,所以在它们之上抛出一个类似集合的接口(interface)是有意义的(所以 __contains__, __iter__, __len__,也许 __or__ 作为 + 的别名,__and__ 作为产品等)。

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

关于python - 避免 Python sum 默认启动 arg 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11624955/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com