python – 如何序列化递归函数?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python – 如何序列化递归函数?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含1843字,纯文字阅读大概需要3分钟。
内容图文
![python – 如何序列化递归函数?](/upload/InfoBanner/zyjiaocheng/771/9ed7b113d5d2469c81f705644c540051.jpg)
假设我有一个通过其闭包递归的函数:
def outer():
def fact(n):
return 1 if n == 0 else n * fact(n - 1)
return fact
我现在想要序列化该函数并使用types.FunctionType重构它:
import pickle, marshal, copyreg, types
def make_cell(value):
return (lambda: value).__closure__[0]
def make_function(*args):
return types.FunctionType(*args)
copyreg.pickle(types.CodeType,
lambda code: (marshal.loads, (marshal.dumps(code),)))
copyreg.pickle(type((lambda i=0: lambda: i)().__closure__[0]),
lambda cell: (make_cell, (cell.cell_contents,)))
copyreg.pickle(types.FunctionType,
lambda fn: (make_function, (fn.__code__, {}, fn.__name__, fn.__defaults__, fn.__closure__)))
buf = pickle.dumps(outer())
fn = pickle.loads(buf)
这适用于普通的闭包,但实际上它会导致无限递归,因为pickle试图在其闭包中序列化事实.在pickle中处理递归数据结构的常用方法是在构造和初始化之间记忆对象,但是函数对象是不可变的,如fn .__ closure__(元组)和单元对象:
>>> cell = (lambda i=0: lambda: i)().__closure__[0]
>>> cell.cell_contents = 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: attribute 'cell_contents' of 'cell' objects is not writable
据推测,在正常代码中构造递归函数时,语言必须做类似的事情,因为函数对象在构造之前不能放在它的闭包中.构建我错过的递归函数是否有一些魔力?
解决方法:
闭包绑定到一个自由变量,而不是它的值.对于自引用闭包,所有Python需要做的是首先为自由事实名创建一个闭包(尚未绑定到任何东西),用闭包创建函数对象,然后将事实绑定到该对象.
因此,您需要将创建闭包和函数组合到同一个外部函数中,这样您就可以为函数绑定的名称创建一个闭包:
def create_closure_and_function(*args):
func = None
def create_function_closure():
return func
closure = create_function_closure.__closure__
func = types.FunctionType(*args[:-1] + [closure])
return func
为了使这个工作与unpickling你必须循环关闭参数(args [-1])并检测有递归的位置,并用create_function_closure .__ closure __ [0]替换那个项目,我想.
内容总结
以上是互联网集市为您收集整理的python – 如何序列化递归函数?全部内容,希望文章能够帮你解决python – 如何序列化递归函数?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。