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

Max*_* Li 3 python

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

sum({1:0,2:10})=3
Run Code Online (Sandbox Code Playgroud)

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

sum(SubDict((1,0),(2,10))=10
Run Code Online (Sandbox Code Playgroud)

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

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

aba*_*ert 9

sum有效地实现如下:

\n\n
def sum(sequence, start=0):\n    for value in sequence:\n        start = start + value\n    return start\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,您不能直接覆盖\xe2\x80\xa6,但如果您可以覆盖序列上的工作sum方式,*或值上的工作方式,这将自动影响。当然,其中任何一个都会产生副作用\xe2\x80\x94,您将影响序列的任何迭代或值的任何添加,而不仅仅是.for value in \xe2\x80\xa6+sumsum

\n\n

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

\n\n
\n\n

但实际上,你为什么要尝试“覆盖总和”?为什么不直接编写一个新函数来完成您想要的功能呢?您可以添加对您的类型进行特殊处理的代码,然后回退到内置类型sum。如果你想让它更加“开放”,你可以使用PEP 443 single-dispatch 来方便地注册新类型以进行特殊处理。我想这就是你真正想要的。

\n\n
\n\n

* 正如 agf 在评论中指出的那样,尽管调用了参数sequence,但它实际上需要任何可迭代对象。这是一件好事,因为字典不是序列\xe2\x80\xa6

\n


Vik*_*kez 6

你可以这样做:

In [1]: sum({1:0,2:10}.values())
Out[1]: 10
Run Code Online (Sandbox Code Playgroud)

如果要实现一个子类,其sum是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
Run Code Online (Sandbox Code Playgroud)

但是你不能做到:

for key in d:
    print d[key]
Run Code Online (Sandbox Code Playgroud)

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

for key in d.keys():
    print d[key]
Run Code Online (Sandbox Code Playgroud)

更好的解决方案是添加一个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
Run Code Online (Sandbox Code Playgroud)

  • 不回答他一般如何做到这一点的问题. (4认同)