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

时间:2016-11-29 21:48:46

标签: python python-3.x python-3.5 python-c-api

我正在尝试测试并修复a bug in pprint++(编辑: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。

具体来说,似乎“普通”内置类型的“实例方法”实现方式略有不同:

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,可以清除)

2 个答案:

答案 0 :(得分:4)

此类型不用于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没有。

请注意,Python 2的情况完全不同。在Python 2中,这种新类型不存在,instancemethod是表示用Python编写的普通方法的方法对象类型的名称。在Python 3中,新类型使用该名称,并且用Python编写的方法的方法对象类型现在命名为method

答案 1 :(得分:2)

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

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