python函数可变对象 python中的可变对象有哪些
Python 中的可变类型对象和不可变类型是什么意思?
不可变数据类型对象是指,当一个对象创建成功后,该变量就记录了一个常量值在内存中的地址.当对该不可变对象进行赋值时,并没有改变对象所代表的常量值,而是重新记录了被赋值对象在内存中的地址,
成都创新互联专业为企业提供嵩明网站建设、嵩明做网站、嵩明网站设计、嵩明网站制作等企业网站建设、网页设计与制作、嵩明企业网站模板建站服务,十余年嵩明做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。
可变数据类型对象可以理解成是一个容器,在这个容器中,可以承载多个相同或不同的数据.并且,容器中的数据可以被替换修改等操作.
Python的可变型和不可变类型知道是什么了吧,如果学习Python不知道去哪里找学习资料,可以看黑马程序员,有学习资料、视频、技术等等!
Python中元祖对象排序
Python中的列表是可变对象,对可变对象可以排序,比如说:L.sort()或者sorted(L),但在元祖数据结构中,因为元祖是不可变对象,不会提供列表中的这些方法,方法就是先将元祖转变为列表,对转变后的列表排序后,再转变回元祖。这样就完成了元祖的排序。
【方法一:】借助于列表中的L.sort()方法
【方法二:】借助于列表中的sorted(L)方法
备注:
Python对象的拷贝
Python赋值操作或函数参数传递,传递的永远是对象引用(即内存地址),而不是对象内容。在Python中一切皆对象,对象又分为可变(mutable)和不可变(immutable)两种类型。对象拷贝是指在内存中创建新的对象,产生新的内存地址。当顶层对象和它的子元素对象全都是immutable不可变对象时,不存在被拷贝,因为没有产生新对象。浅拷贝(Shallow Copy),拷贝顶层对象,但不会拷贝内部的子元素对象。深拷贝(Deep Copy),递归拷贝顶层对象,以及它内部的子元素对象。
Python中一切皆对象,对象就像一个塑料盒子, 里面装的是数据。对象有不同类型,例如布尔型和整型,类型决定了可以对它进行的操作。现实生活中的"陶器"会暗含一些信息(例如它可能很重且易碎,注意不要掉到地上)。
对象的类型还决定了它装着的数据是允许被修改的变量(可变的mutable)还是不可被修改的常量(不可变的immutable)。你可以把不可变对象想象成一个透明但封闭的盒子:你可以看到里面装的数据,但是无法改变它。类似地,可变对象就像一个开着口的盒子,你不仅可以看到里面的数据,还可以拿出来修改它,但你无法改变这个盒子本身,即你无法改变对象的类型。
对象拷贝是指在内存中创建新的对象,产生新的内存地址。
浅拷贝(Shallow Copy),拷贝顶层对象,但不会拷贝内部的子元素对象。
2.1.1. 顶层是mutable,子元素全是immutable
当顶层对象是mutable可变对象,但是它的子元素对象全都是immutable不可变对象时,如[1, 'world', 2]
① 创建列表对象并赋值给变量a
② 导入copy模块,使用copy.copy()函数浅拷贝a,并赋值给变量b
③ 修改变量a的子元素a[0] = 3,由于整数是不可变对象,所以并不是修改1变为3,而是更改a[0]指向对象3
当顶层对象是 mutable可变对象 ,但子元素也存在 mutable可变对象 时,如 [1, 2, ['hello','world']]
① 浅拷贝 copy.copy() 只拷贝了顶层对象,没有拷贝子元素对象['hello','world'],即a[2]和b[2]指向同一个列表对象
② 修改a[2][1] = 'china',则b[2][1] = 'china'
当顶层对象是immutable不可变对象,同时它的子元素对象也全都是immutable不可变对象时,如(1, 2, 3)
变量a与变量b指向的是同一个元组对象,没有拷贝
当顶层对象是immutable不可变对象时,但子元素存在mutable可变对象时,如(1, 2, ['hello','world'])
变量a与变量b指向的是相同的元组对象,并且a[2]与b[2]指向同一个列表,所以修改a[2][1]会影响b[2][1]
深拷贝(Deep Copy),递归拷贝顶层对象,以及它内部的子元素对象
当顶层对象是mutable可变对象,但是它的子元素对象全都是immutable不可变对象时,如[1, 'world', 2]
变量a与变量b指向不同的列表对象,修改a[0]只是将列表a的第一个元素重新指向新对象,不会影响b[0]
当顶层对象是mutable可变对象,但子元素也存在mutable可变对象时,如[1, 2, ['hello','world']]
深拷贝既拷贝了顶层对象,又递归拷贝了子元素对象,所以a[2]与b[2]指向了两个不同的列表对象(但是列表对象的子元素初始指定的字符串对象一样),修改a[2][1] = 'china'后,它重新指向了新的字符串对象(内存地址为140531581905808),不会影响到b[2][1]
当顶层对象是immutable不可变对象,同时它的子元素对象也全都是immutable不可变对象时,如(1, 2, 3)
变量a与变量b指向的是同一个元组对象,不存在拷贝
当顶层对象是immutable不可变对象时,但子元素存在mutable可变对象时,如(1, 2, ['hello','world'])
变量a与变量b指向的是不同的元组对象,同时a[2]与b[2]指向不同的列表对象,所以修改a[2][1]不会影响b[2][1]
使用=是赋值,即将列表对象的引用也赋值给变量b,可以将列表对象想像成一个盒子,变量a相当于这个盒子上的标签,执行b = a后,相当于再在这个盒子上贴上b标签,a和b实际上指向的是同一个对象。因此,无论我们是通过a还是通过b来修改列表的内容,其结果都会作用于双方。
b/c/d都是a的复制,它们都指向了不同的列表对象,但是没有拷贝子元素,a[2]和b[2]/c[2]/d[2]指向同一个列表, 相当于浅拷贝的效果
使用分片[:]操作,a和b其实是指向同一个元组,而且没有拷贝子元素,a[2]和b[2]也指向同一个列表,相当于浅拷贝的效果
同列表类似,可以使用字典的copy()函数或者转换函数dict()
变量a与变量b/c指向不同的字典,但是没有拷贝子元素,a['jobs']和b['jobs']/c['jobs']指定同一个列表, 相当于浅拷贝的效果
同列表类似,可以使用集合的copy()函数或者转换函数set()
变量a与变量b/c指向不同的集合,而集合的元素必须是hashable,所以修改集合a不会影响到b/c
python函数传对象对性能的影响
python函数传对象对性能有影响。在Python中,一切皆对象,Python参数传递采用的都是“传对象引用”的方式。实际上,这种方式相当于传值和传引用的一种综合。如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值,相当于通过“传引用”来传递对象。如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象,相当于通过“传值’来传递对象,此时如果想改变这些变量的值,可以将这些变量申明为全局变量。
Python3 & 浅拷贝与深拷贝
在Python中对象的赋值(=)其实就是对象的引用。即:当创建一个对象,把它赋值给另一个变量时,python并没有拷贝这个对象,只是拷贝了这个对象的引用而已。
Python中对象的拷贝分为:浅拷贝(copy)和深拷贝(deepcopy)。
浅拷贝:拷贝了最外围的对象本身,内部的元素都只是拷贝了一个引用而已。也就是,将原对象在内存中引用地址拷贝过来,然后让新的对象指向这个地址。可以使用“=”或列表自带的copy()函数(如list.copy()),或使用copy模块的copy()函数。
深拷贝:外围和内部元素都进行了拷贝对象本身,而不是引用。即把对象复制一遍,并且该对象中引用的其他对象也同时复制,完全得到一个新的一模一样的对象,对新对象里的值进行修改不会影响原有对象,新对象和原对象完全分离开。深拷贝只能使用copy模块中deepcopy()函数,使用前要导入:from copy import deepcopy。
Python中对象分为不可变对象 、可变对象。
不可变对象:一旦创建就不可修改的对象,例如:字符串、元组、数字
可变对象:可以修改的对象,例如:列表、字典。
其中Python中的切片可以应用于:列表、元组、字符串,但不能应用于字典。
而深浅拷贝,可应用于序列(列表、元组、字符串),也可应用于字典。
其中不可变对象,不管是深拷贝还是浅拷贝,地址值在拷贝后的值都是一样的。
以下以元组(不可变类型)为例
从上述示例可以看出:
不可变对象类型,没有被拷贝的说法,即便是用深拷贝,查看id的话也是一样的,如果对其重新赋值,也只是新创建一个对象,替换掉旧的而已。
所以不可变类型,不管是深拷贝还是浅拷贝,地址值和拷贝后的值都是一样的。
以下以列表(可变类型)为例
第一种方法:使用=号浅拷贝
输出结果:
第二种方法:使用copy浅拷贝
输出结果:
第三种方法:使用deepcopy深拷贝
输出结果:
从上述示例可以看出:
=浅拷贝:值相等,地址相等
copy浅拷贝:值相等,地址不相等
deepcopy深拷贝:值相等,地址不相等
总结:
1,深浅拷贝都是对源对象的复制,占用不同的内存空间。
2,不可变类型的对象,对于深浅拷贝毫无影响,最终的地址值和值都是相等的。
3,可变类型的对象,使用=浅拷贝时, 值相等,地址相等,对新对象里的值进行修改同时会影响原有对象;使用copy浅拷贝时值相等,地址不相等;使用deepcopy深拷贝时值相等,地址不相等。可以看出针对可变类型copy浅拷贝和deepcopy深拷贝,对新对象里的值进行修改不会影响原有对象。
python-进阶-对象变动 a += 1与a = a+1区别
Python中 可变(mutable)与不可变(immutable)的数据类型 让新手很是头痛。简单的说,可变(mutable)意味着"可以被改动",而不可变(immutable)的意思是“常量(constant)”。想把脑筋转动起来吗?考虑下这个例子:
刚刚发生了什么?我们预期的不是那样!
这不是一个bug。这是对象可变性(mutability)在作怪。 每当你将一个变量赋值为另一个可变类型的变量时,对这个数据的任意改动会同时反映到这两个变量上去。新变量只不过是老变量的一个别名而已。这个情况只是针对可变数据类型 。
啊哈!这次又没有达到预期, 是列表的可变性在作怪 。在Python中当函数被定义时,默认参数只会运算一次,而不是每次被调用时都会重新运算。你应该永远不要定义可变类型的默认参数,除非你知道你正在做什么。你应该像这样做:
现在每当你在调用这个函数不传入target参数的时候,一个新的列表会被创建。举个例子:
为什么会出现这样?
a+=b
a=a+b
显然,两者是有区别的,而这种区别只出现在可变对象上(为什么是可变对象后面再说),是什么原因造成了两者的区别呢?
+= 操作调用 __iadd__ 方法,没有该方法时,再尝试调用 __add__ 方法
__iadd__ 方法 直接在原对象a1上进行更新,该方法的返回值为None
+ 操作调用 __add__ 方法
__add__ 方法会返回一个新的对象,原对象不修改,因为这里 a1被重新赋值了,a1指向了一个新的对象,所以出现了文章开头a1不等于a2的情况
为什么前面我说这种差异只会发生的 可变对象 身上?因为对于不可变对象,根本没有 __iadd__ 方法,所以 += 和 + 的效果是一样的,因为调的都是 __add__ 方法
当前文章:python函数可变对象 python中的可变对象有哪些
网页URL:http://scyanting.com/article/hjopci.html