在 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
所以那里使用的术语至少是准确的。可以争论这是否是最好的术语......
我可能将其称为“绑定方法”而不是描述符,但在 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()
并抛出一个错误,然后错误消息会更准确,但这是一个非常疯狂的情况,我不希望经常发生。
要真正了解 Raymond 在编写该代码时的想法,我想您必须问他(或者深入研究 hg 提交历史并希望他在提交消息中提到它)。