Выбор несвязанного метода в Python 3 - PullRequest
9 голосов
/ 28 мая 2010

Я хотел бы выбрать несвязанный метод в Python 3.x. Я получаю эту ошибку:

>>> class A:
...     def m(self):
...         pass
>>> import pickle
>>> pickle.dumps(A.m)
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    pickle.dumps(A.m)
  File "C:\Python31\lib\pickle.py", line 1358, in dumps
    Pickler(f, protocol, fix_imports=fix_imports).dump(obj)
_pickle.PicklingError: Can't pickle <class 'function'>: attribute lookup builtins.function failed

У кого-нибудь есть опыт с этим?


Примечание: в Python 2.x также невозможно выбрать несвязанные методы по умолчанию; Мне удалось сделать это каким-то странным образом, я не понимаю: я написал редуктор с модулем copy_reg для класса MethodType, который охватывает как связанные, так и несвязанные методы. Но редуктор решил только случай связанного метода, потому что он зависел от my_method.im_self. Таинственным образом это также привело к тому, что Python 2.x смог выбрать несвязанные методы. Это не происходит на Python 3.x.

1 Ответ

7 голосов
/ 28 мая 2010

Это нельзя сделать напрямую, потому что в Python 3 несвязанный тип метода пропал: это просто функция:

>>> print (type (A.m))
<class 'function'>

Функции Python не привязаны к классу, поэтому невозможно определить, к какому классу A.m принадлежит, просто взглянув на результат выражения.

В зависимости от того, что именно вам нужно, выбор / удаление набора (класс, имя метода) может быть достаточно хорошим:

>>> print (pickle.loads (pickle.dumps ((A, 'm'))))
... (<class '__main__.A'>, 'm')

Вы можете получить метод (функцию) отсюда, просто используя getattr():

>>> cls, method = pickle.loads (pickle.dumps ((A, 'm')))
>>> print (getattr (cls, method))
... <function m at 0xb78878ec>
...