【发布时间】:2021-12-18 14:08:24
【问题描述】:
我正在使用 mixins 动态创建类,遵循这个 SO 答案中的模式,但它给了我酸洗错误:
https://stackoverflow.com/a/28205308/2056246
(如果有人好奇我到底为什么要这样做,当您可能想要测试不同的操作组合管道时,它对机器学习非常有用)。
这是一个可重复性最低的示例:
class AutoMixinMeta(ABCMeta):
"""
Helps us conditionally include Mixins, which is useful if we want to switch between different
combinations of models (ex. SBERT with Doc Embedding, RoBERTa with positional embeddings).
class Sub(metaclass = AutoMixinMeta):
def __init__(self, name):
self.name = name
"""
def __call__(cls, *args, **kwargs):
try:
mixin = kwargs.pop('mixin')
if isinstance(mixin, list):
mixin_names = list(map(lambda x: x.__name__, mixin))
mixin_name = '.'.join(mixin_names)
cls_list = tuple(mixin + [cls])
else:
mixin_name = mixin.__name__
cls_list = tuple([mixin, cls])
name = "{}With{}".format(cls.__name__, mixin_name)
cls = type(name, cls_list, dict(cls.__dict__))
except KeyError:
pass
return type.__call__(cls, *args, **kwargs)
class Mixer(metaclass = AutoMixinMeta):
""" Class to mix different elements in.
a = Mixer(config=config, mixin=[A, B, C])
"""
pass
class A():
pass
class B():
pass
config={
'test_a': True,
'test_b': True
}
def get_mixins(config):
mixins = []
if config['test_a']:
mixins.append(A)
if config['test_b']:
mixins.append(B)
return mixins
to_mix = get_mixins(config)
c = Mixer(mixin=to_mix)
import pickle
pickle.dump(c, open('tmp/test.pkl', 'wb'))
---------------------------------------------------------------------------
PicklingError Traceback (most recent call last)
<ipython-input-671-a7661c543ef8> in <module>
23
24 import pickle
---> 25 pickle.dump(c, open('tmp/test.pkl', 'wb'))
PicklingError: Can't pickle <class '__main__.MixerWithA.B'>: attribute lookup MixerWithA.B on __main__ failed
我已经阅读了几个专注于使用__reduce__的答案:
https://stackoverflow.com/a/11526524/2056246 https://stackoverflow.com/a/11493777/2056246 Pickling dynamically created classes
但它们都没有在元类级别处理这种动态创建。
以前有没有人遇到过这个问题/知道如何解决它?不幸的是,我对元类知之甚少,无法理解如何解决这个问题。
【问题讨论】: