【问题标题】:python's sum() and non-integer valuespython 的 sum() 和非整数值
【发布时间】:2010-11-16 03:57:09
【问题描述】:

有没有一种简单快捷的方法来使用非整数值的 sum()?

所以我可以这样使用它:

class Foo(object):
    def __init__(self,bar)
        self.bar=bar

mylist=[Foo(3),Foo(34),Foo(63),200]
result=sum(mylist) # result should be 300

我尝试覆盖 __add____int__ 等,但我还没有找到解决方案

编辑:

解决方案是实现:

 def __radd__(self, other):
    return other + self.bar

正如威尔在他的帖子中所建议的那样。但一如既往,条条大路通罗马,但我认为这是最好的解决方案,因为我的课堂不需要__add__

【问题讨论】:

    标签: python list sum


    【解决方案1】:

    试试:

    import operator
    result=reduce(operator.add, mylist)
    

    sum() 可能工作得更快,但它只专门用于内置数字。当然,您仍然必须提供一种方法来添加您的 Foo() 对象。如此完整的例子:

    class Foo(object):
        def __init__(self, i): self.i = i
        def __add__(self, other):
            if isinstance(other, int):
                return Foo(self.i + other)
            return Foo(self.i + other.i)
        def __radd__(self, other):
            return self.__add__(other)
    
    import operator
    mylist = [Foo(42), Foo(36), Foo(12), 177, Foo(11)]
    print reduce(operator.add, mylist).i
    

    【讨论】:

    • from functools import reduce # Py3
    • 这是最通用的解决方案,它适用于实现__add__ 的任何类型,包括那些不适合使用sum(...) 的类型,例如pint 库中带有单位的数量。
    【解决方案2】:

    尝试使用__int__ 方法,然后将列表中的每个元素映射到int 函数以获取值:

    class Foo(object):
        def __init__(self,bar):
            self.bar = bar
        def __int__(self):
            return self.bar
    
    mylist = [Foo(3),Foo(34),Foo(63),200]
    result = sum(map(int,mylist))
    print(result)
    

    【讨论】:

      【解决方案3】:

      或者如果你不想导入任何东西,

      result = reduce((lambda x,y:x+y), mylist)
      

      另一个小优点是,您不必将 __add__ 方法声明为 Foo 对象的一部分,如果这恰好是您想要进行加法的唯一情况。 (但为了未来的灵活性,定义 __add__ 可能不会有什么坏处。)

      【讨论】:

      • 这有一个微妙的问题:如果列表只包含一个元素,那么 (lambda x,y: x+y) 将永远不会被调用,reduce 将返回该单个元素。如果该单个元素是对象而不是整数,则结果是对象而不是总和。
      【解决方案4】:

      您可能还需要实现__radd__ 函数,该函数表示“反向添加”,并在无法在“正向”方向解析参数时调用。例如,如果可能,x + y 被评估为 x.__add__(y),但如果它不存在,那么 Python 会尝试 y.__radd__(x)

      由于sum() 函数以整数0 开头,它所做的第一件事就是尝试评估:

      0 + Foo(3)
      

      这将要求您实现Foo.__radd__

      【讨论】:

      • 知道 0 对我的用例非常有帮助,我正在创建一个可以通过“加法”与自身组合的复杂数据结构。非常感谢您的详尽回答!
      【解决方案5】:

      它有点棘手 - sum() 函数将开始并将其添加到下一个,依此类推

      你需要实现__radd__方法:

      class T:
          def __init__(self,x):
              self.x = x
          def __radd__(self, other):
              return other + self.x
      
      test = (T(1),T(2),T(3),200)
      print sum(test)
      

      【讨论】:

      • 如果要使用int以外的任何其他类型,可以使用sum(test, start=T(0)),否则会报错TypeError: unsupported operand type(s) for +: 'int' and 'str'
      【解决方案6】:

      sum()(没有整数破解)解决方案似乎是最干净的;因为sum()从零开始,处理这种情况(来自http://www.marinamele.com/2014/04/modifying-add-method-of-python-class.html):

      def __radd__(self, other):
          if other == 0:
              return self
          else:
              return other.__add__(self)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-20
        • 2014-05-31
        • 2017-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多