Python是一门面向对象的编程语言,python中一切皆为对象,对每一个对象分配内存空间,python的内存管理机制主要包括引用计数、垃圾回收和内存池机制 。本文简要介绍python对象及内存管理机制 。
参数传递常见的参数传递有值传递和引用传递
- 值传递就是拷贝参数的值,然后传递给新变量,这样原变量和新变量之间互相独立,互不影响 。
- 引用传递指把参数的引用传给新的变量,这样原变量和新变量指向同一块内存地址 。其中任何一个变量值改变,另外一个变量也会随之改变 。
1. 不可变数据类型整型(int)赋值:
a = 1print(id(a))b = aprint(id(b))a = a + 1print(id(a))c = 1print(id(c))
执行结果:140722100085136140722100085136140722100085168140722100085136
其中id()函数用于返回对象的内存地址 。可以看到b,c都指向了相同的对象,而a = a + 1 并不是让 a 的值增加 1,而是重新创建并指向了新的值为 2 的对象 。最终结果就是a指向了2这个新的对象,b指向1,值不变 。
2. 可变数据类型以列表(list)为例:
l1 = [1, 2, 3]print(id(l1)) # l2 = l1print(id(l2))l1.Append(4)print(id(l1))print(l1)print(l2)
执行结果:【Python对象及内存管理机制】
193320277229619332027722961933202772296[1, 2, 3, 4][1, 2, 3, 4]
l1 和 l2 指向相同的对象,由于列表是可变(mutable)数据类型,所以 l1.append(4)不会创建新的列表,仍然指向相同的对象 。由于l1 和 l2 指向相同的对象,所以列表变化也会导致l2的值变化 。可变对象(列表,字典,集合等)的改变,会影响所有指向该对象的变量 。对于不可变对象(字符串、整型、元组等),所有指向该对象的变量的值总是一样的,也不会改变 。
Python中的'==' 和 'is'== 和 is是Python 对象比较中常用的两种方式,== 比较对象的值是否相等, is 比较对象的身份标识(ID)是否相等,是否是同一个对象,是否指向同一个内存地址 。
a = 1b = aprint(id(a))print(id(b))print(a == b)print(a is b)
执行结果:140722100085136140722100085136TrueTrue
a和b的值相等,并指向同一个对象 。在实际应用中,通常使用== 来比较两个变量的值是否相等 。is 操作符常用来检查一个变量是否为 None:if a is None:print("a is None")if a is not None:print("a is not None")
Python浅拷贝和深度拷贝前面介绍了Python的赋值(对象的引用传递),那么Python如何解决原始数据在函数传递后不受影响呢,Python提供了浅度拷贝(shallow copy)和深度拷贝(deep copy)两种方式 。- 浅拷贝(copy):拷贝父对象,不拷贝对象内部的子对象 。
- 深拷贝(deepcopy):完全拷贝了父对象及其子对象 。
import copya = 1b = copy.copy(a)print(id(a))print(id(b))print(a == b)print(a is b)t1 = (1, 2, 3)t2 = tuple(t1)print(id(t1))print(id(t2))print(t1 == t2)print(t1 is t2)
执行结果:5062207250622072TrueTrue5514538455145384TrueTrue
不可变对象的拷贝和对象的引用传递一样,a、b指向相同的对象,修改其中一个变量的值不会影响另外的变量,会开辟新的空间 。2. 可变数据类型对可变对象list进行浅拷贝:
import copyl1 = [1, 2, 3]l2 = list(l1)l3 = copy.copy(l1)l4 = l1[:]print(id(l1))print(id(l2))print(l1 == l2)print(l1 is l2)print(id(l3))print(id(l4))l1.append(4)print(id(l1))print(l1 == l2)print(l1 is l2)
执行结果:4852090448523784TrueFalse485238484852103248520904FalseFalse
可以看到,对可变对象的浅拷贝会重新分配一块内存,创建一个新的对象,里面的元素是原对象中子对象的引用 。改变l1的值不会影响l2,l3,l4的值,它们指向不同的对象 。上面的例子比较简单,下面举一个相对复杂的数据结构:
import copyl1 = [[1, 2], (4, 5)]l2 = copy.copy(l1)print(id(l1))print(id(l2))print(id(l1[0]))print(id(l2[0]))l1.append(6)print(l1)print(l2)l1[0].append(3)print(l1)print(l2)
执行结果:1918057951816191805794944826803289914962680328991496[[1, 2], (4, 5), 6][[1, 2], (4, 5)][[1, 2, 3], (4, 5), 6][[1, 2, 3], (4, 5)]
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 绿茶红茶作用禁忌症,酸枣仁芡实茶的功效与作用及禁忌症
- 莓茶配伍红茶的药效,土家莓茶的作用及功效
- Linux搭建rsync备用服务器,及配置文件详解
- 公共关系专业就业方向及前景
- 柑红茶的功效与作用,由柑柠檬茶的功效与作用及禁忌
- 喝红茶能放冰糖么,冰糖茉莉茶的功效与作用及禁忌
- 红枣红茶水,红枣蜜茶的功效与作用及禁忌
- 红茶可以和金银花,金银花甘草茶的功效和作用及食用方法
- 益母草搭配红茶起,玫瑰花益母草茶的功效与作用及食用方法
- 书包十大品牌及介绍