2015-03-25 3 views
1

Я нашел значительный ответ от этого поста: Is there an easy way to pickle a python function (or otherwise serialize its code)?прекрасно сериализовать функцию в Python

однако, восстановленная функция кажется немного отличается от оригинала, который терпит неудачу моего теста.

Вот пример кода:

import marshal 

# serialize 
f1 = lambda x: x == 0 
c1 = marshal.dumps(f1.func_code) 

# deserialize 
f2 = types.FunctionType(c1, globals()) 

# test 
c1 = marshal.dumps(f1.func_code) 
c2 = marshal.dumps(f2.func_code) 
assert c1 == c2  # fails 

Есть ли у вас какие-либо идеи, как улучшить сериализации/десериализации, чтобы устранить это искажение?

Или любое предложение по части проверки равенства?

PS: учтите только простую лямбду, но не сложное закрытие или обычную функцию.

ответ

1

Дело в том, что вы не можете напрямую сравнивать функциональные переменные, если оба они не ссылаются на один и тот же объект. Вместо этого вы должны сравнить code объектов.

import types 

original = lambda x: x == 0 
code = original.func_code 
recovered = types.FunctionType(code, globals()) 

print(original == recovered) 
print(original.func_code == recovered.func_code) 

Выход:

False 
True 

Давайте добавим некоторую ясность.

a = lamdba : 1 
aa = a 
b = lambda : 1 
c = lambda : 2 

print(a == b) 
print(a == aa) 
print(a.func_code == b.func_code) 
print(a.func_code == c.func_code) 

Выход:

False 
True 
True 
False 

Редактировать. Я протестировал это с помощью вашей функции и сериализации marshal. Работает отлично.

import marshal 
import types 

f = lambda x: x == 0 

with open("test", "rw") as temp: 
    marshal.dump(f.func_code, temp) 
    ff = types.FunctionType(marshal.loads(temp.read()), globals()) 

print(f.func_code == ff.func_code) 

Выход

True 
+0

нормально, мне кажется, что маршал сделал что-то странное, как и marshal.dumps (original.func_code) == marshal.dumps (recovered.func_code) возвращает значение ЛОЖЬ более точно, marshal.loads (marshal.dumps (original.func_code)) == original.func_code возвращает False – Sam

+0

@Sam Ну, это работает для меня. Я добавил пример ответа. –

Смежные вопросы