为什么Counter的__init__方法被称为描述符?

Dav*_*ida 6 python python-datamodel python-3.x

我正在阅读Counter类的__init__方法,并看到了这个:

if not args:
    TypeError("descriptor '__init__' of 'Counter' object "
              "needs an argument")
Run Code Online (Sandbox Code Playgroud)

我不确定描述符是什么意思,所以我检查了python数据模型文档,发现了这个:

通常,描述符是具有"绑定行为"的对象属性,其属性访问权已被描述符协议中的方法覆盖:__ get __(),__ set __()和__delete __().如果为对象定义了任何这些方法,则称其为描述符.

这些方法似乎都没有出现在类定义中,为什么__init_被称为描述符?

mgi*_*son 4

在Python中,所有函数都是描述符(包括__init__)。这实际上就是他们self在课堂上使用它们时知道是什么的方式。例如,我可以定义一个函数 ( foo),然后当我查看它的方法时,我会看到它foo有一个__get__使其遵守描述符协议的方法:

>>> def foo():
...   pass
... 
>>> dir(foo)
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>> '__get__' in dir(foo)
True
Run Code Online (Sandbox Code Playgroud)

所以那里使用的术语至少是准确的。可能会争论这是否是最好的术语......

我可能会称其为“绑定方法”而不是描述符,但在 python3.x 中,常规函数、绑定方法和非绑定方法之间的区别变得更加模糊(非绑定方法python3.x 中的常规函数​​)。 。


当然,我可以使用不同类型的描述符来初始化我的Counter子类......

class MyDescriptor(object):
    def __get__(self, inst, cls):
        # This is a really useless descriptor!
        return Counter.__init__.__get__(inst, cls)

class MyCounter(Counter):
    __init__ = MyDescriptor()
Run Code Online (Sandbox Code Playgroud)

并抛出一个错误,那么错误消息会更准确,但这是一个非常疯狂的情况,我预计不会经常发生。

要真正了解 Raymond 在编写该代码时的想法,我想您必须问他(或者深入研究 hg 提交历史记录并希望他在提交消息中提到它)。