可腌制的动态继承?
Dynamic inheritance that is pickleable?
经过多次搜索,我发现解决我的特定问题的唯一方法是使用动态继承。遵循 here and a few other SO questions; most table is this.
中的指南非常简单
使用第一个 link 中 设计的 示例的修改版本:
def makeinst(cls, *args, **kwargs):
class NewClass(cls): pass
return NewClass(*args, **kwargs)
mylist = makeinst(list,(1,2))
这正如我希望的那样有效,但它不能被腌制:
pickle.dumps(mylist)
...
AttributeError: Can't pickle local object 'makeinst.<locals>.NewClass'
我明白为什么这行不通,但我想知道是否有解决办法?有没有更好的方法来动态子类化某些东西?
(FWIW,dill
也做不到。参见 dill issue #56)
您可以在模块的 global
范围内创建 class,为此您需要使用 type(name, bases, class_dict)
调用手动创建 class
import pickle
def makeinst(name, cls, *args, **kwargs):
# This will be a method
def foo(self):
return f"I am: {self!r}"
globals()[name] = type(
name,
# This must be a tuple
# (cls) evaluate to cls
# (cls,) evaluates to a tuple containing cls as its only element
(cls,),
# Methods, classmethods, staticmethods and all class-level data
{
"foo": foo
},
)
return globals()[name](*args, **kwargs)
my_list = makeinst("MyList", list, [1, 2, 3])
print(my_list) # [1, 2, 3]
data = pickle.dumps(my_list)
my_list_unpickled = pickle.loads(data)
print(my_list_unpickled) # [1, 2, 3]
print(my_list_unpickled.foo()) # I am: [1, 2, 3]
在另一个程序执行中,您必须至少调用一次 makeinst("MyList", list)
才能定义 class。
经过多次搜索,我发现解决我的特定问题的唯一方法是使用动态继承。遵循 here and a few other SO questions; most table is this.
中的指南非常简单使用第一个 link 中 设计的 示例的修改版本:
def makeinst(cls, *args, **kwargs):
class NewClass(cls): pass
return NewClass(*args, **kwargs)
mylist = makeinst(list,(1,2))
这正如我希望的那样有效,但它不能被腌制:
pickle.dumps(mylist)
...
AttributeError: Can't pickle local object 'makeinst.<locals>.NewClass'
我明白为什么这行不通,但我想知道是否有解决办法?有没有更好的方法来动态子类化某些东西?
(FWIW,dill
也做不到。参见 dill issue #56)
您可以在模块的 global
范围内创建 class,为此您需要使用 type(name, bases, class_dict)
调用手动创建 class
import pickle
def makeinst(name, cls, *args, **kwargs):
# This will be a method
def foo(self):
return f"I am: {self!r}"
globals()[name] = type(
name,
# This must be a tuple
# (cls) evaluate to cls
# (cls,) evaluates to a tuple containing cls as its only element
(cls,),
# Methods, classmethods, staticmethods and all class-level data
{
"foo": foo
},
)
return globals()[name](*args, **kwargs)
my_list = makeinst("MyList", list, [1, 2, 3])
print(my_list) # [1, 2, 3]
data = pickle.dumps(my_list)
my_list_unpickled = pickle.loads(data)
print(my_list_unpickled) # [1, 2, 3]
print(my_list_unpickled.foo()) # I am: [1, 2, 3]
在另一个程序执行中,您必须至少调用一次 makeinst("MyList", list)
才能定义 class。