Python:酸洗嵌套函数 [英] Python: pickling nested functions

查看:39
本文介绍了Python:酸洗嵌套函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用示例

def foo(a):
    def bar(b):
        return a+b
    return bar

d = {1:foo(1), 2:foo(2)}

似乎pickle 模块不适用于未在模块范围内定义的函数,因此pickle 'd' 将不起作用.我应该考虑使用另一种酸洗机制吗?

It appears that pickle module will not work with a function not defined at the module scope, so pickling 'd' will not work. Is there another pickling mechanism available that I should consider?

推荐答案

恐怕你不能pickle 嵌套函数.

I'm afraid that you can't pickle nested functions.

pickle 模块按名称序列化函数.也就是说,如果您在模块 mymodule 中有一个函数 myfunc,它只会保存名称 mymodule.myfunc 并在反序列化时再次查找它.(这是一个重要的安全性和兼容性问题,因为它保证反序列化代码使用自己的函数定义,而不是可能被破坏或过时的原始定义.)

The pickle module serializes functions by name. That is, if you have a function myfunc in a module mymodule it simply saves the name mymodule.myfunc and looks it up again when unserializing. (This is an important security and compatibility issue, as it guarantees that the unserializing code uses its own definition for the function, rather than the original definition which might be compromised or obsolete.)

唉,pickle 不能用嵌套函数做到这一点,因为没有办法直接按名称寻址它们.例如,您的 bar 函数无法从 foo 外部访问.

Alas, pickle can't do that with nested functions, because there's no way to directly address them by name. Your bar function, for instance, can't be accessed from outside of foo.

如果您需要一个像函数一样工作的可序列化对象,您可以使用 __call__ 方法创建一个类:

If you need a serializable object that works like a function, you can instead make a class with a __call__ method:

class foo(object):
    def __init__(self, a):
        self.a = a
    def __call__(self, b): # the function formerly known as "bar"
        return self.a + b

这就像问题中的嵌套函数一样工作,应该不会对 pickle 造成任何问题.但请注意,当您反序列化 foo 实例时,您需要具有相同的可用类定义.

This works just like the nested functions in the question, and should pose no problem to pickle. Do be aware though, that you'll need to have the same class definition available when you unserialize a foo instance.

这篇关于Python:酸洗嵌套函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆