当在类范围内定义约束函数和参数时,类实例变为un(dill)pickleable

时间:2017-12-14 15:12:19

标签: python dill lmfit

要使用 lmfit 对象诊断 dill unpickling问题,我想尝试将我的约束函数定义包含在我稍后会选择其实例的类中。但是,转储 dill pickle,其中在类范围内定义约束函数会引发RuntimeError: maximum recursion depth exceeded(下面代码的第(3)节)。

我无法想到为什么会出现这种情况的直观原因。例如,如果我将类范围函数填充到类范围的OrderedDict中,则类实例仍然是 dill pickleable(下面的代码的第(1)部分)。

熟悉 lmfit 的人:知道为什么 lmfit / asteval 会触发此行为?

那些熟悉OOP而不是 lmfit 的人:对可能导致此类问题的代码类型的任何想法?

谢谢!

import dill
import lmfit
from collections import OrderedDict as od

# Python 2.7.13; dill 0.2.7.1; lmfit 0.9.7; numpy 1.13.3; scipy 1.0.0

#%% 1) this works ####################################
class test(object):

    def inside_func(*args):
        return

    def __init__(self):
        # check OrderedDict dill-pickleable (should be)
        self.d = od([])
        self.d.update({'func': self.inside_func})
        return

t = test()

with open('test.pkl', 'wb') as f:
    dill.dump(t, f)


#%% 2) this also works ###############################

def outside_func(*args):
    return

class test(object):

    def __init__(self):
        # some dummy Parameters set 
        self.p = lmfit.Parameters()
        self.p.add('var1')
        self.p.add('var2')

        # addition of 'func' to _asteval's symtable from outside class scope
        self.p._asteval.symtable['func'] = outside_func
        return

t = test()

with open('test.pkl', 'wb') as f:
    dill.dump(t, f)



#%% 3) this doesn't work ###############################

class test(object):
    def inside_func(*args):
        return

    def __init__(self):
        # some dummy Parmaeters set
        self.p = lmfit.Parameters()
        self.p.add('var1')
        self.p.add('var2')

        # addition of 'func' to _asteval's symtable from inside class scope
        if not any('func' == x for x in self.p._asteval.symtable.keys()):
            self.p._asteval.symtable.update({'func': self.inside_func})
        return

t = test()

with open('test.pkl', 'wb') as f:
    dill.dump(t, f)

1 个答案:

答案 0 :(得分:1)

您在错误的地方定义inside_func。在__init__中进行。

这有效:

class test(object):

    def __init__(self):

        def inside_func(*args):
            return

        # some dummy Parmaeters set
        self.p = lmfit.Parameters()
        self.p.add('var1')
        self.p.add('var2')

        # addition of 'func' to _asteval's symtable from inside class scope
        if not any('func' == x for x in self.p._asteval.symtable.keys()):
            self.p._asteval.symtable.update({'func': inside_func})
        return

t = test()

with open('test.pkl', 'wb') as f:
    dill.dump(t, f)

或者,将其设为静态方法:

class test(object):

    @staticmethod
    def inside_func(*args):
        return

    def __init__(self):
        # some dummy Parmaeters set
        self.p = lmfit.Parameters()
        self.p.add('var1')
        self.p.add('var2')

        # addition of 'func' to _asteval's symtable from inside class scope
        if not any('func' == x for x in self.p._asteval.symtable.keys()):
            self.p._asteval.symtable.update({'func': self.inside_func})
        return

t = test()

with open('test.pkl', 'wb') as f:
    dill.dump(t, f)

self.inside_func需要成为"正常"功能。如果不使用staticmethod,Python会将方法绑定到实例。此绑定会触发递归。