简体   繁体   English

Python复制函数传递“字节”对象作为第一个参数

[英]Python copy function passing 'bytes' object as first argument

I have a class, shown below, that inherits from datetime.date 我有一个类,如下所示,该类继承自datetime.date

class my_class(datetime.date):
    def __new__(cls, arg1=None):
        print ("arg1: ", arg1)
        return super().__new__(cls, 2015, 11, 2)

When I copy (or deepcopy ) an instance of this class, as shown below, 当我copy (或deepcopy )此类的实例时,如下所示,

import copy
my_obj = my_class(5)
copy.copy(my_obj)

I get the following output 我得到以下输出

arg1:  5
arg1:  b'\x07\xdf\x0b\x02'

So clearly some bytes object is passed as the first argument when doing a copy (or deepcopy ). 因此很明显,在进行copy (或deepcopy )时, deepcopy某些bytes对象作为第一个参数传递。 I know that the copy function works by passing arguments to the constructor of the object in question such that an identical object will be created...so why is it passing these bytes objects? 我知道copy功能通过将参数传递给相关对象的构造函数而起作用,从而将创建相同的对象...那么为什么要传递这些bytes对象呢?

This behaviour seems to occur only when inheriting from immutable objects, since when I tested this when inheriting from a list object, the copy function did not pass a bytes object. 仅当从不可变对象继承时,才会出现此行为,因为当我从list对象继承时进行了测试时, copy函数未传递bytes对象。

(Note that the class I defined above is a very (very!) simplified case of a real class I am using, that also inherits from datetime.date ) (请注意,我上面定义的类是我正在使用的真实类的非常简化的案例,它也继承自datetime.date

Thanks in advance 提前致谢

NOTE 注意

I am using Python 3.5.1 我正在使用Python 3.5.1

The reason this happens is because internally copy and deepcopy make use of pickle to facilitate object state serialisation. 发生这种情况的原因是,内部copydeepcopy copy使用pickle来促进对象状态序列化。 From the docs : 文档

This module does not copy types like module, method, stack trace, stack frame, file, socket, window, array, or any similar types. 此模块不会复制模块,方法,堆栈跟踪,堆栈框架,文件,套接字,窗口,数组或任何类似类型的类型。 It does “copy” functions and classes (shallow and deeply), by returning the original object unchanged; 它通过不变地返回原始对象来“复制”函数和类(浅层和深层)。 this is compatible with the way these are treated by the pickle module. 这与泡菜模块处理这些食物的方式兼容。

... ...

In fact, the copy module uses the registered pickle functions from the copyreg module. 实际上, copy模块使用copyreg模块中已注册的pickle功能。

Why does copy need to pickle ? 为什么copy需要pickle Because: 因为:

A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original. 浅表副本构造一个新的复合对象 ,然后(在可能的范围内)将对原始对象中找到的对象的引用插入其中。

To do that, though, copy needs to be able to understand the object hierarchy. 为此, copy需要能够理解对象层次结构。 Pickling is designed to solve that problem by mapping a hierarchy to a standard serialised format. 酸洗旨在通过将层次结构映射到标准序列化格式来解决该问题。

This also is where the byte objects come from. 这也是字节对象的来源。

“Pickling” is the process whereby a Python object hierarchy is converted into a byte stream , and “unpickling” is the inverse operation, whereby a byte stream (from a binary file or bytes-like object) is converted back into an object hierarchy. “ Pickling”是将Python对象层次结构转换为字节流的过程 ,而“ unpickling”是逆运算,将字节流(来自二进制文件或类似字节的对象)转换回对象层次结构的过程。

It would appear that, for whatever reason (maybe datetime.date implements __new__ in a special way?), the unpickling isn't reproducing the integer argument passed to __new__ . 看来,无论出于什么原因(也许datetime.date以特殊方式实现__new__ ),取消选择都不会复制传递给__new__的整数参数。

Why? 为什么? I have no earthly idea. 我没有尘世的念头。 Poke around a little bit and see what you can dig up. 戳一点点,看看您可以挖掘出什么。

The Solution 解决方案

The docs also make it pretty clear what to do if copy() or deepcopy() are misbehaving for you - define your own copy implementation! 这些文档还清楚地表明,如果copy()deepcopy()对您而言行为不当,该怎么办-定义自己的复制实现!

In order for a class to define its own copy implementation, it can define special methods __copy__() and __deepcopy__() . 为了让类定义其自己的副本实现,它可以定义特殊的方法__copy__()__deepcopy__()

The former is called to implement the shallow copy operation; 前者被称为实现浅拷贝操作; no additional arguments are passed. 没有传递其他参数。

The latter is called to implement the deep copy operation; 后者被称为实现深度复制操作。 it is passed one argument, the memo dictionary. 它传递了一个参数,即备忘字典。

If the __deepcopy__() implementation needs to make a deep copy of a component, it should call the deepcopy() function with the component as first argument and the memo dictionary as second argument. 如果__deepcopy__()实现需要对组件进行深层复制,则应调用deepcopy()函数,并将该组件作为第一个参数,并将备注字典作为第二个参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM