Python面试高频问题浅拷贝和深拷贝源码分析

发布时间:2023-04-13 14:28:58 作者:iii
来源:亿速云 阅读:88

Python面试高频问题浅拷贝和深拷贝源码分析

在Python面试中,浅拷贝(Shallow Copy)和深拷贝(Deep Copy)是经常被问到的问题。理解它们的区别以及如何在代码中正确使用它们,对于编写高效、可靠的Python代码至关重要。本文将从源码层面分析浅拷贝和深拷贝的实现原理,并通过示例代码帮助读者更好地理解它们。

1. 浅拷贝与深拷贝的基本概念

1.1 浅拷贝

浅拷贝是指创建一个新的对象,但新对象中的元素仍然是原对象中元素的引用。也就是说,浅拷贝只复制了对象的“外壳”,而没有复制对象内部的元素。

import copy

original_list = [[1, 2, 3], [4, 5, 6]]
shallow_copied_list = copy.copy(original_list)

# 修改原对象中的元素
original_list[0][0] = 100

print(original_list)  # 输出: [[100, 2, 3], [4, 5, 6]]
print(shallow_copied_list)  # 输出: [[100, 2, 3], [4, 5, 6]]

在上面的例子中,shallow_copied_listoriginal_list的浅拷贝。当我们修改original_list中的元素时,shallow_copied_list中的对应元素也会被修改,因为它们共享相同的内部引用。

1.2 深拷贝

深拷贝是指创建一个新的对象,并且递归地复制原对象中的所有元素。也就是说,深拷贝不仅复制了对象的“外壳”,还复制了对象内部的元素。

import copy

original_list = [[1, 2, 3], [4, 5, 6]]
deep_copied_list = copy.deepcopy(original_list)

# 修改原对象中的元素
original_list[0][0] = 100

print(original_list)  # 输出: [[100, 2, 3], [4, 5, 6]]
print(deep_copied_list)  # 输出: [[1, 2, 3], [4, 5, 6]]

在上面的例子中,deep_copied_listoriginal_list的深拷贝。当我们修改original_list中的元素时,deep_copied_list中的对应元素不会被修改,因为它们是完全独立的副本。

2. 源码分析

2.1 copy.copy() 的实现

copy.copy() 是Python标准库中用于实现浅拷贝的函数。它的实现逻辑相对简单,主要是通过调用对象的__copy__()方法来实现浅拷贝。

def copy(x):
    """Shallow copy operation on arbitrary Python objects.

    See the module's __doc__ string for more info.
    """
    cls = type(x)

    copier = _copy_dispatch.get(cls)
    if copier:
        return copier(x)

    try:
        issc = issubclass(cls, type)
    except TypeError:  # cls is not a class (old Boost; see SF #502085)
        issc = False
    if issc:
        # treat it as a regular class:
        return _copy_immutable(x)

    copier = getattr(cls, "__copy__", None)
    if copier:
        return copier(x)

    reductor = dispatch_table.get(cls)
    if reductor:
        rv = reductor(x)
    else:
        reductor = getattr(x, "__reduce_ex__", None)
        if reductor:
            rv = reductor(4)
        else:
            reductor = getattr(x, "__reduce__", None)
            if reductor:
                rv = reductor()
            else:
                raise Error("un(shallow)copyable object of type %s" % cls)

    return _reconstruct(x, None, *rv)

从源码中可以看出,copy.copy() 首先尝试通过_copy_dispatch字典查找特定类型的拷贝函数。如果找不到,则尝试调用对象的__copy__()方法。如果对象没有__copy__()方法,则尝试通过__reduce_ex__()__reduce__()方法来获取对象的拷贝。

2.2 copy.deepcopy() 的实现

copy.deepcopy() 是Python标准库中用于实现深拷贝的函数。它的实现逻辑相对复杂,主要是通过递归地复制对象及其内部的所有元素。

def deepcopy(x, memo=None, _nil=[]):
    """Deep copy operation on arbitrary Python objects.

    See the module's __doc__ string for more info.
    """
    if memo is None:
        memo = {}

    d = id(x)
    y = memo.get(d, _nil)
    if y is not _nil:
        return y

    cls = type(x)

    copier = _deepcopy_dispatch.get(cls)
    if copier:
        y = copier(x, memo)
    else:
        try:
            issc = issubclass(cls, type)
        except TypeError:  # cls is not a class (old Boost; see SF #502085)
            issc = False
        if issc:
            y = _deepcopy_atomic(x, memo)
        else:
            copier = getattr(cls, "__deepcopy__", None)
            if copier:
                y = copier(x, memo)
            else:
                reductor = dispatch_table.get(cls)
                if reductor:
                    rv = reductor(x)
                else:
                    reductor = getattr(x, "__reduce_ex__", None)
                    if reductor:
                        rv = reductor(4)
                    else:
                        reductor = getattr(x, "__reduce__", None)
                        if reductor:
                            rv = reductor()
                        else:
                            raise Error("un(deep)copyable object of type %s" % cls)
                y = _reconstruct(x, memo, *rv)

    memo[d] = y
    _keep_alive(x, memo)  # Make sure x lives at least as long as d
    return y

从源码中可以看出,copy.deepcopy() 首先通过memo字典来避免循环引用导致的无限递归。然后,它尝试通过_deepcopy_dispatch字典查找特定类型的深拷贝函数。如果找不到,则尝试调用对象的__deepcopy__()方法。如果对象没有__deepcopy__()方法,则尝试通过__reduce_ex__()__reduce__()方法来获取对象的深拷贝。

3. 使用场景与注意事项

3.1 使用场景

3.2 注意事项

4. 总结

浅拷贝和深拷贝是Python中非常重要的概念,理解它们的区别和实现原理对于编写高效、可靠的代码至关重要。通过本文的源码分析,我们可以更深入地理解Python中浅拷贝和深拷贝的实现机制,并在实际应用中正确使用它们。

在面试中,掌握浅拷贝和深拷贝的区别及其使用场景,能够帮助你在面对相关问题时游刃有余。希望本文能够帮助你更好地理解这一高频面试问题。

推荐阅读:
  1. 如何用Python制作小型图书管理系统
  2. Python中怎么利用Requests实现网络请求

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

python

上一篇:怎么巧妙使用MySQL WHERE子句

下一篇:linux是否支持动态路由

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》