Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何将选项传递给deepcopy?_Python_Python 3.x_Pickle_Deep Copy - Fatal编程技术网

Python 如何将选项传递给deepcopy?

Python 如何将选项传递给deepcopy?,python,python-3.x,pickle,deep-copy,Python,Python 3.x,Pickle,Deep Copy,在中,Anthony Hatchkins给出了一个基于dict复制代码的deepcopy的默认实现,Python采用了该代码: def __deepcopy__(self, memo): cls = self.__class__ result = cls.__new__(cls) memo[id(self)] = result for k, v in self.__dict__.items(): setattr(result, k, deepcop

在中,Anthony Hatchkins给出了一个基于dict复制代码的deepcopy的默认实现,Python采用了该代码:

def __deepcopy__(self, memo):
    cls = self.__class__
    result = cls.__new__(cls)
    memo[id(self)] = result
    for k, v in self.__dict__.items():
        setattr(result, k, deepcopy(v, memo))
    return result
我想要一个基于pickle和unpickle的默认实现,Python在返回到dict复制之前选择pickle和unpickle

以下是我的尝试,但没有成功:

def __deepcopy__(self, memo):
    new, args, state = self.__reduce__()
    result = new(*args)
    if state:
        result.__setstate__(state)
    memo[id(self)] = result
    return result
一旦我有了这样一种方法,我就可以制作一个版本,其中包含关于复制内容和复制方式的附加选项

reduce和setstate的存在由一个基类保证,该基类定义:

@staticmethod
def kwargs_new(cls, new_kwargs, *new_args):
    """
    Override this method to use a different new.
    """
    retval = cls.__new__(cls, *new_args, **new_kwargs)
    retval.__init__(*new_args, **new_kwargs)
    return retval


"""
Define default getstate and setstate for use in coöperative inheritance.
"""
def __getstate__(self):
    return {}

def __setstate__(self, state):
    self.__dict__.update(state)

def __getnewargs_ex__(self):
    return ((), {})

def __reduce__(self):
    """
    Reimplement __reduce__ so that it calls __getnewargs_ex__
    regardless of the Python version.

    It will pass the keyword arguments to object.__new__.
    It also exposes a kwargs_new static method that can be overridden for
    use by __reduce__.
    """

    new_args, new_kwargs = self.__getnewargs_ex__()
    state = self.__getstate__()

    return (type(self).kwargs_new,
            (type(self), new_kwargs,) + tuple(new_args),
            state)

传递给setstate的状态需要复制,参数列表也需要复制:

def __deepcopy__(self, memo):
    """
    Reimplement __deepcopy__ so that
    * it supports keyword arguments to reduce.
    """
    kwargs = memo.get('deepcopy kwargs', {})
    new, args, state = self.__reduce__(**kwargs)
    args_copy = copy.deepcopy(args, memo)
    result = new(*args_copy)
    memo[id(self)] = result
    if state:
        state_copy = copy.deepcopy(state, memo)
        result.__setstate__(state_copy)
    return result

此版本的deepcopy已被修改为使用一个特殊的备注来传递要减少的关键字参数。

另一个选项是通过让reduce检查堆栈帧来传递要减少的关键字参数:

def f():
    import inspect
    for frame_tuple in inspect.stack():
        if 'x' in frame_tuple[0].f_locals:
            x = frame_tuple[0].f_locals['x']
    print(x)

def g():
    x = 5

    f()

g()

为什么您需要基于pickle的解决方案?我看不出有什么好处。另外,让pickler备忘录和deepcopy备忘录很好地协同工作可能是一个问题。@user2357112:因为这样我就可以免费得到pickle了。我可以使用相同的代码来实现保存和加载。通过实现pickle协议,例如通过重写uu getstate_uuuuuuuu和u setstate_uuuu,您可以免费获得深度复制。可能是相关的。@shx2:是的,这就是我最后做的。基类仍然需要上面的代码来处理getnewargs_ex等。