不带自变量的__init__函数定义

时间:2018-12-14 22:01:47

标签: python

在研究Counter中的python collections类时,我发现了一些我认为很奇怪的东西:他们没有在self函数的变量中显式使用__init__参数。论点。

请参见下面的代码(不带文档字符串直接复制):

class Counter(dict):
    def __init__(*args, **kwds):
        if not args:
            raise TypeError("descriptor '__init__' of 'Counter' object "
                            "needs an argument")
        self, *args = args
        if len(args) > 1:
            raise TypeError('expected at most 1 argments, got %d' % len(args))
        super(Counter, self).__init__()
        self.update(*args, **kwds)

稍后在同一类中,updatesubtract方法也以相同的方式定义。

在向我提出有关self在课堂上的工作方式的问题之前,我会指出,我不认为这是重复的问题。我了解self的工作原理,并且self不是关键字(只是标准做法)等。我也了解此代码有效(我不怀疑*的有效性unpack / explode / starred-expressions语法)

我的问题与为什么...

  • 为什么一个人会实现此类的__init__和其他普通的(非@static / @class方法),我将来应该在什么情况下考虑使用它?
  • 为什么只在同一类上实现特定的方法?
  • 在什么情况下会在没有任何参数(如果有)的情况下调用这些方法,从而触发第一个TypeError?
  • 在什么情况下可以手动填充self(例如Counter.__init__(some_counter))来调用这些方法?还是其他例子?

我必须认为这与TypeError(“ descriptor ...”)有关。

1 个答案:

答案 0 :(得分:18)

此代码旨在使self仅在位置上。否则,类似

的呼叫
d = {'self': 5}
Counter(**d)

由于__init__收到两个self值而失败。

大多数类不需要这种特殊处理,但是Counter应该像dict这样处理关键字参数,即使它们是{ {1}}。具有这种处理方式的其他'self'方法是需要相同的关键字参数行为的方法。

如果您需要在自己的代码中将Counter作为有效的关键字参数,则应该做类似的事情。


对于self,在那里可以匹配来自TypeError的错误消息:

dict.__init__

在实践中最可能实现此目的的方法可能是人们将>>> dict.__init__() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: descriptor '__init__' of 'dict' object needs an argument >>> Counter.__init__() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.7/collections/__init__.py", line 560, in __init__ raise TypeError("descriptor '__init__' of 'Counter' object " TypeError: descriptor '__init__' of 'Counter' object needs an argument 子类化,而忘记将Counter传递给self(或使用Counter.__init__)。