zoukankan      html  css  js  c++  java
  • python中隐式的内存共享

    在python中,基本上使用的是引用,那么就会造成一个隐式的内存共享,特别是在容器对象中,例如list,dictionary


    对于不可变对象,是不会造成隐式的内存共享情况,如下所示:

    >>> alist = [0]*5
    >>> print alist
    [0, 0, 0, 0, 0]
    >>> alist[0]= 'kel'
    >>> alist
    ['kel', 0, 0, 0, 0]
    以上为不可变对象数字类型,数字是不可变对象,在每次都会新建这一对象。

    >>> alist = ['kel']*5
    >>> alist
    ['kel', 'kel', 'kel', 'kel', 'kel']
    >>> alist[0]='changed'
    >>> alist
    ['changed', 'kel', 'kel', 'kel', 'kel']
    字符串也是不可变类型,从而在修改一个对象的时候,其他的对象都会重新建立


    在多维数组列表中,则会造成隐式的内存共享,也就是修改其中一个的值其他的值也会发生改变,如下所示:

    >>> multi = [[0]*5]*3
    >>> multi
    [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
    >>> multi[0][0]='kel'
    >>> multi
    [['kel', 0, 0, 0, 0], ['kel', 0, 0, 0, 0], ['kel', 0, 0, 0, 0]]
    当使用列表解析的时候,会造成隐式内存共享,在每次使用的时候,都是指向同一个对象,具体的如下所示:

    >>> row = [0]*5  
    >>> multi = [row]*3
    >>> multi
    [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
    >>> multi[0][0]='kel'
    >>> multi
    [['kel', 0, 0, 0, 0], ['kel', 0, 0, 0, 0], ['kel', 0, 0, 0, 0]]
    1、 row中的五个子项都引用0 -——在这个时候修改其中之一的值,不会影响其他的值,因为是不可变对象

    2、multi中的3个子项都引用row——从而在修改最里面的值的时候,都会影响其他的值,因为指向的是同一个对象row


    如果对象是不可变的,则对象和对象引用实际上没什么区别。


    要解决内存共享的问题,那么可以使用双层循环的列表解析,而不是使用直接使用重复的列表解析:

    >>> mmultilist = [[0 for x in range(3)] for x in range(5)]
    >>> mmultilist
    [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
    >>> mmultilist[0][0]='kel'
    >>> mmultilist
    [['kel', 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
    在进行修改的时候,没有影响到其他的值,从而这种方法是可以的。

    另外,在使用这种双层循环的方式中,可以对开始的进行简化,从而代码如下:

    >>> multilist=[[0]*3 for x in range(5)]
    >>> multilist
    [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
    >>> multilist[0][0] = 'kel'
    >>> multilist
    [['kel', 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
    当直接使用列表乘以整数的时候,可以直接得到列表的重复,注意在这里如果是不可变对象,那么可以使用;如果涉及到了几维数据的话,那么就必须使用其中的循环从而消除对内存共享的影响。

    此种问题对于可变对象才会发生,而对于不可变对象是不会发生的。







    for linux and python
  • 相关阅读:
    封装异常处理之坑
    30multipart/form-data和application/x-www-form-urlencoded的区别(二)urlencoded之自动deocde
    使用MAT时的Shallow Size和 Retained Size的区别
    当动态代理遇到ioc
    线程池的原理
    synchroned原理与对象头(yet)
    mysql压力测试与qps监控
    一种mysql jvm死锁
    Android Jni变量对照表
    结构体中使用函数指针
  • 原文地址:https://www.cnblogs.com/kellyseeme/p/5525045.html
Copyright © 2011-2022 走看看