如何实现类的内置sum()?

时间:2013-08-08 21:31:11

标签: python

应用于字典的内置函数sum()返回其键的总和:

sum({1:0,2:10})=3

我想创建字典的子类,比如SubDict,并覆盖一些函数来返回其值的总和,即

sum(SubDict((1,0),(2,10))=10

我需要覆盖哪个功能才能实现此功能?

P.S。这是一个普遍的问题,如何在类中实现内置的sum()函数,而不仅仅是在这种特殊情况下。

2 个答案:

答案 0 :(得分:6)

你可以这样做:

In [1]: sum({1:0,2:10}.values())
Out[1]: 10

如果要实现一个子类,其总和将是值sum,只需覆盖__iter__方法:

In [21]: class MyDict(dict):
   ....:     def __iter__(self):
   ....:         for value in self.values():
   ....:             yield value
   ....:

In [22]: d = MyDict({1:0,2:10})

In [23]: sum(d)
Out[23]: 10

但是你不能做到:

for key in d:
    print d[key]

因为__iter__函数会返回值...您将始终必须使用keys()函数:

for key in d.keys():
    print d[key]

更好的解决方案是添加sum方法:

In [24]: class MyDict(dict):
   ....:     def sum(self):
   ....:         return sum(self.values())
   ....:

In [25]: d = MyDict({1:0,2:10})

In [26]: d.sum()
Out[26]: 10

答案 1 :(得分:3)

sum实际上是这样实现的:

def sum(sequence, start=0):
    for value in sequence:
        start = start + value
    return start

因此,您无法直接覆盖sum ...但如果您可以覆盖for value in …对序列的处理方式,*或+对您的值的处理方式,那么自动影响sum。当然,任何一个都会产生副作用 - 你会影响你的序列的任何迭代,或你的值的任何添加,而不仅仅是{{1}内的那些}。

要覆盖迭代,您需要提供一个返回适当迭代器的sum方法。要覆盖添加,您需要提供__iter__方法。


但实际上,你为什么试图“超越总和”?为什么不写一个能做你想要的新功能呢?您可以添加特殊情况下的代码类型,然后返回内置__add__。如果你想让它更“开放”,你可以使用PEP 443单一调度来轻松注册特殊的新类型。我认为这就是你真正想要的东西。


*正如agf在评论中指出的那样,尽管参数被称为sum,但它实际上需要任何迭代。这是一件好事,因为字典不是序列......