python - 腌制部分类
问题描述
我需要部分实例化一个类,然后在多处理中使用。多处理泡菜类在进程之间传递。如何腌制部分实例化的类?
我的目标是 Python 3.8+
PS这是我的partialclass
实现:
def partialclass(cls, *args, **kwargs):
new_cls = type(cls.__name__, (cls,), {})
new_cls.__init__ = partialmethod(cls.__init__, *args, **kwargs)
return new_cls
编辑:我考虑过覆盖__reduce__
方法,但类可能会接受参数,我在定义时不知道。
解决方案
您正在创建一个类,而不是“部分实例”。Pickle 不序列化类,因为它假定所有代码都可以从源代码加载。
相反,生成一个实用程序类的实例,一个可以腌制的实例,并且在调用时与调用生成的类执行相同的操作:
class Partial:
def __init__(self, cls, *args, **kwargs):
self.cls, self.args, self.kwargs = cls, args, kwargs
def __call__(self, *args, **kwargs):
return self.cls(*self.args, *args, **self.kwargs, **kwargs)
然后对类属性进行腌制(这里是对类对象、元组和字典的引用),您可以调用实例来生成实际的类:
>>> import pickle
>>> class Foo:
... def __init__(self, *args, **kwargs):
... self.a, self.k = args, kwargs
... def __repr__(self):
... return f"<Foo(*{self.a!r}, **{self.k!r})>"
...
>>> pickled = pickle.dumps(Partial(Foo, "bar", monty="python"))
>>> partial = pickle.loads(pickled)
>>> partial("baz", spam="ham")
<Foo(*('bar', 'baz'), **{'monty': 'python', 'spam': 'ham'})>
但是,上面基本上是重新发明functools.partial()
object,它们是可以腌制和调用的实用程序类的实例,就像上面的 Python 重新实现一样:
>>> import pickle
>>> from functools import partial
>>> pickled = pickle.dumps(partial(Foo, "bar", monty="python"))
>>> fpartial = pickle.loads(pickled)
>>> fpartial("baz", spam="ham")
<Foo(*('bar', 'baz'), **{'monty': 'python', 'spam': 'ham'})>
functools.partial()
但是,内存效率更高,速度更快。
唯一可能的优势是您可以使用isinstance(object, Partial)
它与functools.partial()
. 但是您也可以为此使用子类化:
import functools
class CPartial(functools.partial): pass
它的工作原理是一样的。
推荐阅读
- kubernetes - 如何确保 pod 的可访问性
- c# - 有没有办法以编程方式使用任何 google 站点 api 在 google 站点中添加站点通知一次性消息?
- node.js - 保护后端 API 端点(MERN 应用程序)
- paypal - PayPal 根据使用情况向用户收费
- tcp - TCPDUMP BPF 原语和端口排除
- python - 如何将新实例初始化为*现有实例?
- sql-server - 使用 ASP 页从 SQL Server 存储过程返回数据
- python - 此代码是否会更改列表中每个元素的值?
- amazon-web-services - 在 terraform 中使用其他 tf 文件的输出
- tesseract - 训练后的tesseract结果仍然很差