• Python引用复制,参数传递,弱引用与垃圾回收


    引用

    先上个示例:

    >>> val = [1]
    >>> val[0] = val
    >>> val
    [[...]]

    上述代码使val中包含自身,而产生了无限递归。上述示例表明Python中的变量名为引用类型,赋值只是使得左值指向与右值相同的内存对象。

    is运算符可以判断两个引用是否指向了同一个对象,而==运算符判断两个引用指向的值是否相等而不关心指向什么对象。

    对引用不了解的朋友,可以把Python引用与C/C++中的void *类比,不过因为垃圾回收机制Python引用无需担心内存泄漏的问题。

    复制

    上面的示例表明赋值无法为对象建立副本,python中的copy模块提供了copydeepccopy建立副本。

    示例:

    >>> import copy
    >>> a = [[1, 2, 3], [4, 5, 6]]
    >>> b = a
    >>> c = copy.copy(a)
    >>> d = copy.deepcopy(a)
    >>> a.append(7)
    >>> a[1][2] = 0
    >>> a
    [[1, 2, 3], [4, 5, 0], 7]
    >>> b
    [[1, 2, 3], [4, 5, 0], 7]
    >>> c
    [[1, 2, 3], [4, 5, 0]]
    >>> d
    [[1, 2, 3], [4, 5, 6]]

    浅复制copy.copy只复制父引用指向的对象,其子引用仍指向原来的内存对象,而深复制copy.deepcopy则会复制所有引用指向的对象。deepcopy 本质上是递归 copy。

    示例中的副本c,d父对象是a的副本所以a.append方法对它们没有影响。

    但是copy.copy创建的副本c中的元素仍指向与a相同的内存对象,而deepcopy创建的d则指向了自己的元素。

    tuple和frozenset之类的容器只是保证其中引用指向不变,但是引用指向的内存对象仍然是可变的。容器的切片对象的机制为浅复制。

    x = x + y,必须创建新的临时变量然后进行浅复制,性能较差。

    x += y,无需新建临时对象,只在内存块末尾增加元素,性能较好。

    参数传递

    Python中的参数传递采用浅复制的值传递。

    示例:

    >>> def swap(a,b):
    ...   b,a=a,b
    ...
    >>> a = 1
    >>> b = 2
    >>> swap(1,2)
    >>> a
    1
    >>> b
    2

    上述示例证明,Python参数传递是采用值传递的方式。

    示例2:

    >>> def fun(a):
    ...   a[0] = 2
    ...
    >>> a = [1]
    >>> fun(a)
    >>> a
    [2] 

    这个示例则证明采用浅复制的方法进行传递。

    垃圾回收

    Python中的垃圾回收是以引用计数为主,标记-清除和分代收集为辅。

    一组对象互相引用的情况称为循环引用(交叉引用),若出现这种情况引用计数将无法正确的回收垃圾。,可以包含其他对象引用的容器对象(如list, dict, set,甚至class)都可能产生循环引用。

    标记 - 清除

    “标记-清除”法是为了解决循环引用问题。

    垃圾标记时,先将集合中对象的引用计数复制一份副本(以免在操作过程中破坏真实的引用计数值),然后操作这个副本,遍历对象集合,将被引用对象的引用计数副本值减1。

    根据引用计数副本值是否为0将集合内的对象分成两类,reachable和unreachable,其中unreachable是可以被回收的对象。

    分代回收

    分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。

    弱引用

    弱引用是避免循环引用的一种方法,弱引用不记录引用计数。当一个对象只有弱引用时可能被垃圾回收器回收。

    weakref.ref(obj,[callable])用于建立一个指向obj的弱引用,当对象被回收前callable可选参数指定的函数将被执行以进行清理工作。

    Python引用的那些坑

    使用GC分析Python垃圾回收机制

    CPython源代码分析垃圾回收机制

  • 相关阅读:
    再谈Linux内核中的RCU机制
    Linux下的crontab定时执行任务命令详解
    Linux 2.6内核中新的锁机制--RCU
    linux内核自锁旋spinlock常用宏解释
    Linux内核list/hlist解读
    Linux下0号进程的前世(init_task进程)今生(idle进程)----Linux进程的管理与调度(五)
    Linux下的进程类别(内核线程、轻量级进程和用户进程)以及其创建方式--Linux进程的管理与调度(四)
    Linux进程ID号--Linux进程的管理与调度(三)
    内核源码阅读(三)进程命名空间和用户命名的实现
    Linux的命名空间详解--Linux进程的管理与调度(二)
  • 原文地址:https://www.cnblogs.com/yechanglv/p/6947305.html
Copyright © 2020-2023  润新知