Python __不带自参数的init__;函数定义

Python __不带自参数的init__;函数定义,python,Python,在深入研究集合中的python计数器类时,我发现了一个我认为很奇怪的地方:它们没有在\uuuu init\uuu函数的参数中显式使用self参数 请参阅下面的代码(直接复制而不使用docstring): 在同一类的后面部分,update和subtract方法也以同样的方式定义 在你向我提出关于self如何在课堂上工作的问题之前,我要指出,我不认为这是一个重复的问题。我理解self通常是如何工作的,并且self不是一个关键词(只是标准实践)等等。我也理解该代码是如何工作的(我并不质疑*解包/分解/

在深入研究
集合
中的python
计数器
类时,我发现了一个我认为很奇怪的地方:它们没有在
\uuuu init\uuu
函数的参数中显式使用
self
参数

请参阅下面的代码(直接复制而不使用docstring):

在同一类的后面部分,
update
subtract
方法也以同样的方式定义

在你向我提出关于
self
如何在课堂上工作的问题之前,我要指出,我不认为这是一个重复的问题。我理解
self
通常是如何工作的,并且
self
不是一个关键词(只是标准实践)等等。我也理解该代码是如何工作的(我并不质疑
*
解包/分解/星号表达式语法的有效性)

我的问题是为什么

    <>为什么要实现一个类的代码< >代码> <代码> >和其他正常的(非<代码>静态> /代码> /<代码> @类>代码>方法),在什么情况下我应该考虑使用这个?
  • 为什么同一个类上只有特定的方法是这样实现的
  • 在什么情况下,在没有任何参数(如果有)的情况下调用这些方法,从而触发第一个TypeError
  • 在什么情况下,手动填写
    self
    (例如
    Counter.\uuuuu init\uuuuu(某些计数器)
    )会调用这些方法?还是其他例子
我不得不认为这与TypeError(“描述符…”)有关


编辑11/2020: 在Python3.8中,引入了仅位置参数,从而无需以这种方式使用
(*args,**kwds)
。这可以从以下内容中看到:

def\uuuuu init\uuuuuuu(self,iterable=None,/,**kwds):

此代码仅用于使
自身处于位置。否则,像

d = {'self': 5}
Counter(**d)
由于
\uuuu init\uuuu
接收到两个
self
值,将失败

大多数类不需要像这样的特殊处理,但是
计数器
应该像
dict
那样处理关键字参数,在这里它们成为结果映射的键,即使键是
'self'
。其他具有此处理的
计数器
方法是需要相同关键字参数行为的方法

如果您需要在自己的代码中将
self
视为有效的关键字参数,您可能应该做类似的事情


至于
TypeError
,它与来自
dict的错误消息相匹配

>>> 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
>>dict.\uuuuu init\uuuuu()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:“dict”对象的描述符“\uuuu init\uuuuuu”需要参数
>>>计数器
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/usr/lib/python3.7/collections/_init__.py”,第560行,in__init__
raise TypeError(“计数器”对象的描述符“\uuuuu init\uuuuuuuuuu”
TypeError:“Counter”对象的描述符“\uuuuu init\uuuuuuu”需要参数

在实践中,最可能出现这种情况的方法可能是人们将
计数器子类化,而忘记将
self
传递给
计数器.

它确实使用self:
self,*args=args
。我喜欢这个!非常聪明的东西。对
类型错误本身有什么简短的解释吗?我很理解它为什么在那里,但它是什么意思:“描述符”?@StephenCowley:The是方法在实例上访问时用来自动绑定
self
参数的协议。它不仅有用,而且是方法使用它的目的。大多数C方法使用的描述符类型称为“type\u name”的“descriptor”method\u name“需要参数”如果在没有
self
位置参数的情况下调用。
>>> 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