精华内容
下载资源
问答
  • 主要介绍了Python可变对象和不可变对象的相关资料,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
  • 主要介绍了Python可变对象与不可变对象原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • Python里和None比较时,为什么是 is None 而不是 == None 呢?...这是因为None在Python里是个单例对象,一个变量如果是None,它一定和None指向同一个内存地址。而 == None背后调用的是__eq__,而__eq__可以被重载
  • Python在heap中分配的对象分成两类:可变对象和不可变对象。所谓可变对象是指,对象的内容是可变的,例如list。而不可变的对象则相反,表示其内容不可变。 不可变对象:int,string,float,tuple(故其成员...

    Python在heap中分配的对象分成两类:可变对象和不可变对象。所谓可变对象是指,对象的内容是可变的,例如list。而不可变的对象则相反,表示其内容不可变。

    • 不可变对象:int,string,float,tuple(故其成员函数一般有返回值,返回新对象)
    • 可变对象   :list,dictionary(故其成员函数一般没有返回值,直接修改)

    一、不可变对象

    由于Python中的变量存放的是对象引用,所以对于不可变对象而言,尽管对象本身不可变,但变量的对象引用是可变的。运用这样的机制,有时候会让人产生糊涂,似乎可变对象变化了。如下面的代码:

    Java代码   收藏代码
    1. i = 73  
    2. i += 2  


     

     

    从上面得知,不可变的对象的特征没有变,依然是不可变对象,变的只是创建了新对象,改变了变量的对象引用。

    看看下面的代码,更能体现这点的。

     

    Java代码   收藏代码
    1. #因为258int对象,是不可变对象的。所以下面3个id的值都是一样的,最后一句的结果也是为True  
    2. #有点奇怪的是为什么在IDLE,和在脚本执行的结果不太一样。所以下面的代码请在脚本中执行。  
    3.   
    4. print(id(258))  
    5. a = 258  
    6. print(id(a))  
    7. b = 258  
    8. print(id(b))  
    9. print(a is b)  

     

     

     

     

    二、对于可变对象

    其对象的内容是可以变化的。当对象的内容发生变化时,变量的对象引用是不会变化的。如下面的例子。

    Python代码   收藏代码
    1. m=[5,9]  
    2. m+=[6]  

     

     
    展开全文
  • 在本篇文章里小编给大家分享了是一篇关于python可变对象和不可变对象的基础知识点内容,有需要的朋友们可以参考下。
  • python精讲 不可变对象可变对象

    千次阅读 2020-07-22 15:46:35
    python中,可变对象包括:list、set、dict、自定义对象; 不可对对象包括:int、float、str、bool、tuple等。 不可变对象步允许自身内容进行修改。如果我们队一个不可变对象进行赋值,实际上是生成一个新对象,再...

    对象(object)

    cpu,内存,硬盘之间的关系:

    CPU与内存间的工作关系为:
    当我们在计算机上执行一个程序时,首先由输入设备向CPU发出操作指令,

    CPU接收到操作指令后,硬盘中对应的程序指令被直接加载到内存中,此

    后,CPU再对内存进行寻址操作,将加载到内存中的指令翻译出来,而后

    发送操作信号给操作控制器,实现程序的运行或数据的处理。

    对象

    • 对象即在内存中存储数据的一块区域
    • Python 中的变量不是装有对象的“容器”,而是贴在对象上的“标签”。
      真正的存贮位置是内存中
    - 每个对象都有三个要素:id(标识)(唯一性,每个对象都有唯一的id)
    					  type(类型)(决定对象的功能)
    					  value(值)(对象存储的数据值)
    

    对象

    • 在python中,可变对象包括:list、set、dict、自定义对象;
    • 不可对对象包括:int、float、str、bool、tuple等。
    • 不可变对象步允许自身内容进行修改。如果我们队一个不可变对象进行赋值,实际上是生成一个新对象,再让变量指向这个对象。哪怕这个对象简单到只是数字0和1

    每个对象在内存中都会存储三个数据:
    1.id(标识)
    2.type(类型)
    3.value(值)

    可变对象与不可变对象

    可变对象

    而可变对象即指在对象不改变的前提下让对象的数据发生改变
    即值发生改变但是 对象 未发生改变,例如 标识id 不会发生改变

    a = [1,2,3]
    print('修改前',a,id(a))
    a[0] = 4  #改变了值
    print('修改后',a,id(a))  #但是id未变
    
    修改前 [1, 2, 3] 1221617771648
    修改后 [4, 2, 3] 1221617771648
    

    对象没有发生改变而值发生改变
    a[0]=4

    重新赋值则开辟新的内存块存储新的值,顶替原来的对象和值
    在这里插入图片描述

    a = [1,2,3]
    print('修改前',a,id(a))
    a = [2,3,4]  #重新赋值即重新建立一个a,所以这个a不是原来的a,
                 #而是新生的a
    print('修改后',a,id(a))  #所以内存中重新开辟空间,对象发生改变
    
    修改前 [1, 2, 3] 2057897038528
    修改后 [2, 3, 4] 2057897038720
    

    因为对象不可变,所以为了提高效率,Python 会使用一些公用的对象:

    a = 1
    print('a', id(a))
    b = 1
    print('b', id(b))
    print(a == b)
    print(a is b)
    c = 'hello world'
    print('c', id(c))
    d = 'hello world'
    print('d', id(d))
    print(c == d)
    print(c is d)
    

    输出:

    a 4423761776
    b 4423761776
    True
    True
    c 4430180912
    d 4430180912
    True
    True
    

    这里顺便提一下 is 这个操作符。它和 == 的区别在于:== 只判断“值”是不是相等,而 is 则判断是否为同一个对象,也就是地址一致。比如:

    a = 2
    b = 2.0
    print(a == b)
    print(a is b)
    

    输出:

    True
    False
    

    不可变对象

    不可变对象不允许对自身内容进行修改。如果我们对一个不可变对象进行赋值,实际上是生成一个新对象,再让变量指向这个对象。:
    即重新赋值

    a = 0
    print('a', id(a))
    a = 1
    print('a', id(a))
    

    输出:

    a 4463151440
    a 4463151472
    

    在这里插入图片描述

    展开全文
  • 下面小编就为大家带来一篇浅谈Python中的可变对象和不可变对象。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • python中的可变对象与不可变对象

    千次阅读 2018-12-20 22:40:20
    python与C/C++不一样,它的变量使用有自己的特点,...下面本文将对python里面的“可变数据类型”和“不可变数据类型”进行分析。 首先,我们需要知道在python中哪些是可变数据类型,哪些是不可变数据类型。可变数据...

    python与C/C++不一样,它的变量使用有自己的特点,当初学python的时候,一定要记住“一切皆为对象,一切皆为对象的引用”这句话,其实这个特点类似于JAVA,所以在python里面大家也不用担心类似于C/C++中的指针的复杂问题。下面本文将对python里面的“可变数据类型”和“不可变数据类型”进行分析。

    首先,我们需要知道在python中哪些是可变数据类型,哪些是不可变数据类型。可变数据类型:列表list和字典dict,set,自己定义的类对象,numpy中的ndarray对象,具体参考:NumPy:拷贝和视图。不可变数据类型:整型int、浮点型float、字符串型string和元组tuple,以及frozenset。(注意:字典的key只能是不可变对象,即字典的key只能是整型int、浮点型float、字符串型string和元组tuple)

    set(): 一种可变的、无序的、有限的集合,其元素是唯一的、不可变的(可哈希的)对象。
    frozenset(): 一种不可变的、可哈希的、无序的集合,其元素是唯一的,不可变的哈希对象。

    其次需要注意,python中的变量保存的都是值所在的地址,例如 a = 10,a保存的是10所在的地址。这里的可变与不可变指的是指向可变或者不可变。

    然后,我们以int和list为例,来看看“可变数据类型”和“不可变数据类型”到底有什么区别。

    (1) 不可变数据类型分析 。先来看一段程序:

    >>> x = 1
    >>> id(x)
    31106520
    >>> y = 1
    >>> id(y)
    31106520
    >>> x == y
    True
    >>> x is y #具有相同值的不可变对象(例如整数)是同一对象
    True
    >>> x = 2
    >>> id(x)
    31106508
    >>> y = 2
    >>> id(y)
    31106508
    >>> z = x
    >>> id(x)
    31106508
    >>> x += 2
    >>> id(x) # 只要不可变对象指向的值发生变化,不可变对象就会重新指向新的值(即4)所在的地址
    31106484 
    >>>x
    4
    >>>z  #x都已经指向了新的值所在地址,所以肯定不会影响z的值
    2
    

    内存驻留机制的影响

    >>>a = "Hello_World"
    >>>b = "Hello_World"
    >>>a is b 
    True
    >>>a = "Hello World"   # 字符串中出现了非标识符时,不采用驻留,所以a与b不指向同一内存地址
    >>>b = "Hello World"
    >>>a is b
    False
    >>>a = -5
    >>>b = -5
    >>>a is b
    True
    >>>a = -6
    >>>b = -6
    >>>a is b
    False
    >>>a = 256
    >>>b = 256
    >>>a is b
    True
    >>>a = 257
    >>>b = 257   # 整型的界限是(-5,256),只有这个范围内才驻留
    >>>a is b
    False
    
    >>> str1='sten'+'waves'
    >>> str2 is 'stenwaves'
    True
    >>> str3='sten'
    >>> str4=str3+'waves'
    >>> str4 is 'stenwaves' 
    False
    
    注:驻留适用范围:由数字,字符和下划线(_)组成的python标识符以及整数[-5,256]。 驻留时机 :python中的驻留发生在compile_time,而不是run_time。

    上面这段程序都是对不可变数据类型中的int类型的操作,id()查看的是当前变量的地址值。我们先来看x = 1和y = 1两个操作的结果,从上面的输出可以看到x和y在此时的地址值是一样的,也就是说x和y其实是引用了同一个对象,即1,也就是说内存中对于1只占用了一个地址,而不管有多少个引用指向了它,都只有一个地址值,只是有一个引用计数会记录指向这个地址的引用到底有几个而已。当我们进行x = 2赋值时,发现x的地址值变了,虽然还是x这个引用,但是其地址值却变化了,后面的y = 2以及z = y,使得x、y和z都引用了同一个对象,即2,所以地址值都是一样的。当x和y都被赋值2后,1这个对象已经没有引用指向它了,所以1这个对象占用的内存,即31106520地址要被“垃圾回收”,即1这个对象在内存中已经不存在了。最后,x进行了加2的操作,所以创建了新的对象4,x引用了这个新的对象,而不再引用2这个对象。

    那么为什么称之为不可变数据类型呢?这里的不可变大家可以理解为x引用的地址处的值是不能被改变的,也就是31106520地址处的值在没被垃圾回收之前一直都是1,不能改变,如果要把x赋值为2,那么只能将x引用的地址从31106520变为31106508,相当于x = 2这个赋值又创建了一个对象,即2这个对象,然后x、y、z都引用了这个对象,所以int这个数据类型是不可变的,如果想对int类型的变量再次赋值,在内存中相当于又创建了一个新的对象,而不再是之前的对象。从下图中就可以看到上面程序的过程。
    在这里插入图片描述
    从上面的过程可以看出,不可变数据类型的优点就是内存中不管有多少个引用,相同的对象只占用了一块内存,但是它的缺点就是当需要对变量进行运算从而改变变量引用的对象的值时,由于是不可变的数据类型,所以必须创建新的对象,这样就会使得一次次的改变创建了一个个新的对象,不过不再使用的内存会被垃圾回收器回收。

    (2)可变数据类型分析。下面同样先看一段程序。

    >>> a = [1, 2, 3]
    >>> id(a)
    1468022383176
    >>> b = [1, 2, 3]
    >>> id(b)
    1468022383048
    >>> a == b #比较的是值
    True
    >>> a is b #具有相同值的可变对象(例如list)是不同的对象
    False
    >>> c = a
    >>> a.append(4)
    >>> id(a)
    1468022383176
    >>> a += [2] #与不可变对象不同,可变对象并不是只要改变其值就会指向新地址,只有给可变对象赋新的值或者某些场景下可变对象才会指向新的地址。比如 +=就不会让可变对象指向新的地址。而 = +却会指向新地址。
    >>> id(a)
    1468022383176
    >>> a
    [1,2,3,4,2]
    >>> id(c)
    1468022383176
    >>> c  # c会与a同步变化
    [1,2,3,4,2]
    >>> a = a +[9]   #a会指向新地址
    >>>id(a)
    1467885024648
    >>>a
    [1,2,3,4,2,9]
    >>>c     #a与c已经不指向同一地址,所以a的变化肯定不会影响c了
    [1,2,3,4,2]
    >>>id(c)
     1468022383176 
    

    从上面的程序中可以看出,进行a = [1, 2, 3] 和 b=[1,2,3] 操作,两次值相同的对象引用的地址是不同的,也就是说其实创建了两个不同的对象,这一点明显不同于不可变数据类型,所以对于可变数据类型来说,具有同样值的对象是不同的对象,即在内存中保存了多个同样值的对象,地址值不同。接着来看后面的操作,我们对列表进行添加操作,分别a.append(4)和a += [2],发现这两个操作使得a引用的对象值变成了上面的最终结果,但是a引用的地址依旧是1468022383176,也就是说对a进行的操作不会改变a引用的地址值,只是在地址后面又扩充了新的地址,改变了地址里面存放的值(注意:a += [2] 与 a = a + [2]是不同的,后者会指向新地址,*=同理。),所以可变数据类型的意思就是说对一个变量进行操作时,其值是可变的,值的变化并不会引起新建对象,即地址是不会变的,只是地址中的内容变化了或者地址得到了扩充。下图对这一过程进行了图示,可以很清晰地看到这一过程。
    在这里插入图片描述

    从上述过程可以看到,可变数据类型是允许同一对象的内容,即值可以变化,但是地址是不会变化的。但是需要注意一点,对可变数据类型的操作不能是直接进行新的赋值操作,比如说a = [1, 2, 3, 4, 5, 6, 7],这样的操作就不是改变值了,而是新建了一个新的对象,这里的可变只是对于类似于append、+=等这种操作。

    总之,用一句话来概括上述过程就是:“python中的不可变数据类型,不允许变量的值发生变化,如果改变了变量的值,相当于是新建了一个对象,而对于相同的值的对象,在内存中则只有一个对象,内部会有一个引用计数来记录有多少个变量引用这个对象;可变数据类型,允许变量的值发生变化,即如果对变量进行append、+=等这种操作后,只是改变了变量的值,而不会新建一个对象,变量引用的对象的地址也不会变化,不过对于相同的值的不同对象,在内存中则会存在不同的对象,即每个对象都有自己的地址,相当于内存中对于同值的对象保存了多份,这里不存在引用计数,是实实在在的对象。”

    python函数的参数传递

    由于python规定参数传递都是传递引用,对象赋值是对象的引用,且一切都是对象,所以一切赋值都是引用,也就是传递给函数的是原变量实际所指向的内存空间(就把python中函数的参数传递理解成赋值号(=),即让形参指向实参指向的位置),修改的时候就会根据该引用的指向去修改该内存中的内容,所以按道理说我们在函数内改变了传递过来的参数的值的话,原来外部的变量也应该受到影响。但是上面我们说到了python中有可变类型和不可变类型,这样的话,当传过来的是可变类型(list,dict)时,我们在函数内部修改就会影响函数外部的变量。而传入的是不可变类型时在函数内部修改改变量并不会影响函数外部的变量,因为修改的时候会先复制一份再修改。下面通过代码证明一下:

    def test(a_int, b_list):
        a_int = a_int + 1
        b_list.append('13')
        print('inner a_int:' + str(a_int))
        print('inner b_list:' + str(b_list))
    
    if __name__ == '__main__':
        a_int = 5
        b_list = [10, 11]
        test(a_int, b_list)
        print('outer a_int:' + str(a_int))
        print('outer b_list:' + str(b_list))
    

    运行结果如下:

    inner a_int:6
    
    inner b_list:[10, 11, '13']
    
    outer a_int:5
    
    outer b_list:[10, 11, '13']
    

    所以,当函数形参是可变对象(list,dict等)时,要想在函数内部修改改变量时不影响函数外部的变量,可以给函数形参传递可变对象的拷贝,这里有深浅两种拷贝,参见下面的文章

    这篇文章看完之后,可以看下面这篇,很有相关性。

    NumPy:拷贝和视图

    展开全文
  • Python中的可变对象和不可变对象

    千次阅读 2017-12-11 10:25:31
    Python在heap中分配的对象分成两类:可变对象和不可变对象。所谓可变对象是指,对象的内容是可变的,例如list。而不可变的对象则相反,表示其内容不可变。不可变对象:int,string,float,tuple 可变对象 :l

    python变量赋值(可变与不可变)

    知识点:python中,万物皆对象。
         python中不存在所谓的传值调用,一切传递的都是对象的引用,也可以认为是传址。
    Python在heap中分配的对象分成两类:可变对象和不可变对象。所谓可变对象是指,对象的内容是可变的,例如list。而不可变的对象则相反,表示其内容不可变。

    不可变对象:int,string,float,tuple
    可变对象 :list,dictionary
    一、不可变对象

    由于Python中的变量存放的是对象引用,所以对于不可变对象而言,尽管对象本身不可变,但变量的对象引用是可变的。运用这样的机制,有时候会让人产生糊涂,似乎可变对象变化了。如下面的代码:

    i=73
    i=i+2
    不可变对象不变,引用变了
    这里写图片描述

    不可变的对象的特征没有变,依然是不可变对象,变的只是创建了新对象,改变了变量的对象引用。
    看看下面的代码,更能体现这点的。

    print(id(100)) # 1362346144
    a = 100
    print(id(a)) # 1362346144
    b = 100
    print(id(b)) # 1362346144
    但如果变成258则id就有变化

    print(id(258)) # 1659053321968
    a = 258
    print(id(a)) # 1659053321968
    b = 258
    print(id(b)) # 1659053319280
    为何不一样了?

    (答案转自知乎问题:为什么Python有相同的不可变对象id不同?或者知乎原答案)

    二、可变对象
    这里写图片描述
    其对象的内容是可以变化的。当对象的内容发生变化时,变量的对象引用是不会变化的。

    关于此问题的大坑:函数默认参数的使用
    先定义一个函数,传入一个list,添加一个END再返回:
    def add_end(L=[]):
    L.append(‘END’)
    return L
    当你正常调用时,结果似乎不错:

    >>> add_end([1, 2, 3])
    [1, 2, 3, 'END']
    >>> add_end(['x', 'y', 'z'])
    ['x', 'y', 'z', 'END']

    当你使用默认参数调用时,一开始结果也是对的:

    >>> add_end()
    ['END']

    但是,再次调用add_end()时,结果就不对了:

    >>> add_end()
    ['END', 'END']
    >>> add_end()
    ['END', 'END', 'END']

    很多初学者很疑惑,默认参数是[],但是函数似乎每次都“记住了”上次添加了’END’后的list。
    原因解释如下:
    Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。
    所以,定义默认参数要牢记一点:默认参数必须指向不变对象!
    要修改上面的例子,我们可以用None这个不变对象来实现:

    def add_end(L=None):
        if L is None:
            L = []
        L.append('END')
        return L

    现在,无论调用多少次,都不会有问题:

    >>> add_end()
    ['END']
    >>> add_end()
    ['END']

    为什么要设计str、None这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。

    作者:五秋木
    链接:http://www.jianshu.com/p/b690422ec02a
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    展开全文
  • Python可变对象和不可变对象

    千次阅读 2017-02-13 12:56:21
    之前写了FPGrowth的代码,写得非常恶心,觉得和C语言、C++的工程文件很不相同。其中就有关于传引用、传值的疑问。截一段Leetcode的代码这题好像是Leetcode ...经过查看资料我就知道这和命名域以及可变对象和不可变对象
  • 1. 什么是对象python中一切皆为对象!—PPT 程序运行当中,所有数据都是储存到内存当中再运行的。 对象就是内存中专门用来存储数据的一块区域。 对象实际上就是一个容器,专门用来存储各种数据.(比如:数值、字符...
  • 可变对象 与 不可变对象我们知道在python中一切皆对象。在python世界中可以把对象大体分成两大类:不可变对象:数字(int,float, double)、字符串、元组(tuple)、function等可变对象:字典(dict)、列表(list)...
  • 可变对象 vs 不可变对象Python

    千次阅读 2016-08-27 22:27:57
    Python 在 heap 中分配的对象分成两类:可变对象和不可变对象。所谓可变对象是指,对象的内容是可变的,例如 list。而不可变的对象则相反,表示其内容不可变。 不可变对象:int,string,float,tuple 可变对象 :...
  • python的可变和不可变对象

    千次阅读 2016-04-29 14:59:36
    python的对象分为可变对象(mutable)和不可变对象(immutable) 不可变对象(immutable)包括:常数、字符串、元组和不可变集合(frozensets) 可变对象包括:列表、字典、自定义类对象(也可用特殊方法定义为不可变类) ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 187,780
精华内容 75,112
关键字:

python可变对象

python 订阅