在阅读这篇文章之前,我知道我正在尝试在python中做一些非常规的事情。因为"不做x"不是答案"我该如何做x?"让我们假设有一个很好的理由去做,尽管在大多数情况下这不是一个好习惯。
鉴于我有一个通过将一个装饰器应用于一个函数来动态创建的类,我将如何去挑选一个所述类的实例?
例如,要设置它,它可能如下所示:
import inspect
from functools import wraps
class BaseClass:
pass
def _make_method(func):
""" decorator for adding self as first argument to function """
@wraps(func)
def decorator(self, *args, **kwargs):
return func(*args, **kwargs)
# set signature to include self
sig = inspect.signature(decorator)
par = inspect.Parameter('self', 1)
new_params = tuple([par] + list(sig.parameters.values()))
new_sig = sig.replace(parameters=new_params,
return_annotation=sig.return_annotation)
decorator.__signature__ = new_sig
return decorator
def snake2camel(snake_str):
""" convert a snake_string to a CamelString """
return "".join(x.title() for x in snake_str.split('_'))
def make_class(func):
""" dynamically create a class setting the call method to function """
name = snake2camel(func.__name__) # get the name of the new class
method = _make_method(func)
cls = type(name, (BaseClass,), {'__call__': method})
return cls()
@make_class
def something(arg):
return arg
现在有些东西是动态创建的类Something
的实例。
type(something) # -> __main__.Something
isinstance(something, BaseClass) # -> True
工作正常,但当我尝试腌制它(或使用在引擎盖下使用泡菜的多处理模块)时:
import pickle
pickle.dumps(something) # -> raises
它会抛出此错误:
# PicklingError: Can't pickle <class '__main__.Something'>: attribute lookup Something on __main__ failed
所以我认为我可以重新定义BaseClass
以使用 reduce 方法,如下所示:
class BaseClass:
def __reduce__(self):
return make_class, (self.__call__.__func__,)
然后它抛出可怕的&#34;不是同一个对象&#34;错误:
# PicklingError: Can't pickle <function something at 0x7fe124cb2d08>: it's not the same object as __main__.something
如何在不引入依赖关系的情况下完成此工作?我需要能够挑选something
对象,这样我就可以使用python 3.6中concurrent.futures模块的ProcessPoolExecutor
类,所以简单地使用dill或cloudpickle可能不是一个选项。