将自定义(深层)复制逻辑添加到python类的正确方法

wou*_*lee 11 python

我正在实现一个提供一些嵌套数据结构的python类.我希望添加对复制copy.copy()和深度复制的支持copy.deepcopy(),正如复制模块描述的文档所涉及的那样,它涉及编写__copy__()__deepcopy__特殊方法.

我知道如何教我的班级自己复制,但我想避免__init__()在新实例上进行,因为__init__()我的复制逻辑不需要(或不需要)做一些事情.

我最终得到的是这种方法,它按预期工作:

def __copy__(self):
    cls = type(self)
    obj = cls.__new__(cls)
    # custom copying logic that populates obj goes here
    return obj
Run Code Online (Sandbox Code Playgroud)

我的问题是:是否正在cls.__new__(cls)__copy__()想要跳过__init__()副本的实现调用正确的方法?还是有一种我忽略的"pythonic"方法?

Nat*_*rth 1

我不知道这是否更Pythonic,但你可以使用一个标志。

from collections import Mapping
from copy import copy, deepcopy


class CustomDict(dict, Mapping):
    _run_setup = True

    def __init__(self, *args, **kwargs):
        self._dict = dict(*args, **kwargs)
        if args and isinstance(args[0], CustomDict):
            self._run_setup = args[0]._run_setup
        if self._run_setup:
            print("Doing some setup stuff")
        else:
            try:
                print("Avoiding some setup stuff")
            finally:
                self._run_setup = True

    def __getitem__(self, key):
        return self._dict[key]

    def __iter__(self):
        return iter(self._dict)

    def __len__(self):
        return len(self._dict)

    def __copy__(self):
        self._run_setup = False
        try:
            copied_custom_dict = CustomDict(self)
        finally:
            self._run_setup = True
        return copied_custom_dict
Run Code Online (Sandbox Code Playgroud)

__init__上面,条件设置仅在 if 时完成_run_setup = True。避免这种情况的唯一方法是使用CustomDict第一个参数作为其自身的实例进行调用_run_setup = False调用。这样,就可以轻松地以不同的方法翻转设置开关。

这些try...finally块对我来说看起来很笨重,但这是一种确保每个方法都以 . 开头和结尾的方法_run_setup = True