应用于字典的内置函数sum()返回其键的总和:
sum({1:0,2:10})=3
我想创建字典的子类,比如SubDict,并覆盖一些函数来返回其值的总和,即
sum(SubDict((1,0),(2,10))=10
我需要覆盖哪个功能才能实现此功能?
P.S。这是一个普遍的问题,如何在类中实现内置的sum()函数,而不仅仅是在这种特殊情况下。
答案 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
,但它实际上需要任何迭代。这是一件好事,因为字典不是序列......