简单的魔术_随手可变的小魔术
在Python的世界里,万物皆为对象。虽然同为对象,却有可变与不可变之分。我们经常通过赋值操作来实现对象间的“拷贝”,但实际上,因为Python的“变量标签模型”,这种操作仅仅是两个标签指向了同一个对象。
Python提供了浅拷贝和深拷贝的功能,用于处理不同对象类型的问题。当我们需要对对象的拷贝行为进行特殊定制时,可以通过定义特殊的魔术方法来达成目的。
文章内容概要如下:
一、赋值操作下的对象“复制”实质
二、浅拷贝与深拷贝的运作原理
三、利用魔术方法控制拷贝行为
由于Python的独特设计理念,其变量赋值并非简单的盒子模型,而是更为复杂的标签模型。
通过赋值实现的“复制”实际上仍然是同一个对象,通过id()函数可以轻易验证这一点。这一部分的内容前面已经介绍过,此处不再赘述。
除了简单的赋值和新建对象外,Python的copy模块提供了更为便捷的对象拷贝方式。
从官方文档中,我们可以找到关于浅拷贝(shallow copy)和深拷贝(deep copy)的详细说明。
简而言之:
1. 对于像列表、字典这样的可变对象,浅拷贝会生成一个全新的对象(具有不同的id),但其内部内容与原对象完全相同。如果容器内部包含可变类型的元素,浅拷贝仅指代原对象的元素。
2. 对于可变对象,深拷贝则会递归地复制其自身及所有元素的内容,直到遇到不可变对象为止。
3. 对于不可变对象,浅拷贝通常不会生成新的对象。
4. 对于包含不可变对象和可变对象的复杂结构,深拷贝的处理方式会根据具体情况而变化:若不可变对象的内部元素也都是不可变对象,则不会进行拷贝;若内部元素是可变对象,则会先创建新对象,再递归处理其内部的可变对象。
接下来,我们通过代码示例来验证浅拷贝与深拷贝的实际运用。
执行结果:
从执行结果中,我们可以清晰理解可变对象在浅拷贝与深拷贝下的处理逻辑。
再来验证一下不可变对象的浅拷贝与深拷贝情况。
首先观察一下,当不可变对象的内部元素也都是不可变对象时的拷贝情况:
执行结果:
可见,此时并没有创建新的对象。
而对于一个包含可变对象的不可变对象呢?
执行结果:
在面对内部含有可变对象的不可变对象时,深拷贝会穿透外层的不可变包装,直到内部的元素全部为不可变对象为止。
我们来看看当自定义类型遇到浅拷贝和深拷贝时的默认行为:
执行结果:
从结果中可以看出,自定义类型的浅拷贝和深拷贝机制与内置类型在本质上是一致的。
如果需要自定义浅拷贝与深拷贝的行为,可以通过实现__copy__()和__deepcopy__()这两个魔术方法来实现。
1.__copy__()方法,用于定义浅拷贝的行为。
2.__deepcopy__()方法,用于定义深拷贝的行为。
下面我们通过代码简单演示一下这两个魔术方法的使用。
本文详细介绍了赋值、浅拷贝、深拷贝三种对象“复制”的方式,比较了它们的运行机制。通过代码演示了如何通过魔术方法自定义浅拷贝和深拷贝的行为。