我在哪里可以找到 Python 3 标准库中的实例方法?

Where can I find an instancemethod in the Python 3 standard library?

我正在尝试测试并修复即将出现的 a bug in pprint++ (edit: the correct link; original link left for posterity),因为 instancemethod 类型不可哈希:

In [16]: import pandas as pd

In [17]: type(pd.tslib.NaT).__repr__
Out[17]: <instancemethod __repr__ at 0x1058d2be8>

In [18]: hash(type(pd.tslib.NaT).__repr__)
   ...
TypeError: unhashable type: 'instancemethod'

但是我在测试这个问题时遇到了问题,因为我不知道在 Python 3 标准库中还能在哪里找到 instancemethod,而且我不想要我的测试依赖于 Pandas.

具体来说,"normal" 内置类型似乎有 "instance methods",它们的实现略有不同:

In [19]: type(None).__repr__
Out[19]: <slot wrapper '__repr__' of 'NoneType' objects>

In [20]: hash(type(None).__repr__)
Out[20]: -9223372036583849574

所以:我在哪里可以找到 Python 3 标准库中的 instancemethod,以便我可以针对它编写测试?还是那里没有出现的特殊类型?

(注意:这似乎只影响 Python 3,因为 Python 2 中的相同方法是一个 unbound method,它是可散列的)

此类型未用于 Python 附带的任何内容,并且没有 Python 级 API 来创建此类型的对象。但是,您可以通过直接 C API 调用来完成:

import ctypes

PyInstanceMethod_New = ctypes.pythonapi.PyInstanceMethod_New
PyInstanceMethod_New.argtypes = (ctypes.py_object,)
PyInstanceMethod_New.restype = ctypes.py_object

arbitrary_callable = sum

instance_method = PyInstanceMethod_New(arbitrary_callable)

名称 instancemethod 看起来很像绑定方法对象,但事实证明它完全是另外一回事。这是一个奇怪的内部事物,根据其 documentation,应该是 C 类型表示其方法的新方式,除了用于创建类型的标准 C 级别 API 不会实际使用它。

根据 Python 问题跟踪器上的 conversations,Cython 和 Pyrex 的开发人员要求此功能。看起来 pandas.tslib.NaT 是在 Cython 中实现的,而 Cython 实现实际上使用了这种类型,而用于创建类型的标准 C API 却没有。

注意Python2的情况完全不同。在Python2,这个新类型不存在,instancemethod是方法类型的名称表示用 Python 编写的普通方法的对象。在 Python 3 中,新类型采用了该名称,在 Python 中编写的方法的方法对象类型现在命名为 method.

Python 提供它,但基本上只是作为他们的测试套件 AFAICT 的一部分(不包含电池否则使用它)。您可以使用 _testcapi 模块制作一个用于测试:

>>> import _testcapi
>>> testinstancemethod = _testcapi.instancemethod(str.__repr__)
>>> hash(testinstancemethod)
...
TypeError: unhashable type: 'instancemethod'