Маринованные обернутые частичные функции

Я пытаюсь создать подобрать декоратор с использованием частичных функций. Тем не менее, я продолжаю получать ошибки травления при попытке сделать это.

Первый наивный пример выглядит следующим образом:

def decorator(func):
  def wrapper(**kwargs):
    return partial(func, **kwargs)
  return wrapper

@decorator
def decorated(x, y=1, z=2):
  return x+y+z

y5 = decorated(y=5)
pickle.dumps(y5)

куда partial взят из functools,

Чуть менее наивная попытка включает добавление @wraps на одну строку выше def wrapper, Это не помогает

Я не уверен, что понимаю, как работает травление.

1 ответ

Проблема в вашем декораторе, а не с частичным. Частичный объект должен просто мариновать:

>>> from pickle import *
>>> from functools import *
>>> f = partial(pow, 2)
>>> p = dumps(f)
>>> g = loads(p)
>>> g(5)
32

Итак, эта проблема с вашим кодом находится в декораторе. Это не сохранение имени исходной функции. Попробуйте это вместо этого:

import pickle
from functools import *

def decorator(func):
    def wrapper(**kwargs):
        return partial(func, **kwargs)
    return wrapper

def decorated(x, y=1, z=2):
    return x+y+z

dd = decorator(decorated)

y5 = dd(y=5)
pickle.dumps(y5)

Модификация для использования dd должен позволить логике pickle обнаруживать основную функцию по ее имени. Так работают соленья.

Чтобы увидеть имя функции в pickle, посмотрите на вывод dumps:

>>> print pickle.dumps(y5)
cfunctools
partial
p0
(c__main__
decorated
p1
tp2
Rp3
(g1
(t(dp4
S'y'
p5
I5
sNtp6
b.

Слово "украшенный" должно быть найдено, соответствовать основной функции и не быть скрытым декоратором. Помните, что когда функции подвергаются травлению, сохраняются только их имена. Фактическое содержание функции не в рассоле.

Есть некоторые обходные пути, но они не красивые. Вы можете использовать __setstate__() для сохранения как имени функции, так и ее исходного кода. Затем добавьте метод __getstate__(), чтобы восстановить функцию, выполнив ее источник.

Кроме того, вы можете извлечь байтовые коды из объекта объекта функции и сохранить их. После восстановления скомпилируйте объект кода и выполните его.

Короче говоря, ваша цель использования декоратора с нотацией @ напрямую расходится с тем, как работает выбор функций. Чтобы достичь своей цели, вам нужно настроить функцию выбора функции, чтобы сохранить то, что делает функция, а не только ее имя.

Другие вопросы по тегам