与c/c++不同,Python/Java中的变量都是引用类型,没有值类型
Python赋值语句由三部分构成,例如:
int a = 1
类型 标识 值
标识(identity):用于唯一标识一个对象(指向对象的内存地址);类型(type);值(value)
Python使用标识访问对象的值,也就是说Python中的对象其实相当于c的指针
引用(reference):对象的内存地址
可变类型:重新赋值时直接更改内存中原有对象,变量引用不变。float、list、dict
不可变类型:重新赋值时在内存中创建一个新对象,同时改变变量的引用。int、char、tuple
这样设置是为了提高效率,比如1、2这样的变量可能经常被用到,一次定义多次引用的话效率会比较高
知道了Python变量的内存机制,就可以避免一些坑。比如而a、b的类型都是List,令a=b后,对a、b任意一个List进行修改,都会影响另外一个List的值,因为他们实际指向同一个内存地址
要注意区分“对象(object)”和“变量(variable)”,对象是在程序中创建的,储存在内存中,变量是对象的引用(reference),变量赋值是让变量指向对象,一个对象可以被多个变量指向
python中所有的数据类型都是对象
可变对象(列表、字典、集合)的改变会影响所有指向该对象的变量
不可变对象(字符串、整型、元组),所有指向该对象的变量的值总是一样的,也不会改变,通过某些操作更新其值时会返回一个新的对象【一旦创建,不可改变】
变量可以被删除,但对象不可以,只能被垃圾回收机制回收
1 l1=[1,2,3] 2 print(id(l1)) 3 l1.append(4) 4 l2=[1,2,3] 5 l3=l2 6 print(id(l1)) 7 print(id(l2)) 8 print(id(l3)) 9 10 v1=1 11 print(id(v1)) 12 v1=2 13 v2=1 14 v3=v2 15 print(id(v1)) 16 print(id(v2)) 17 print(id(v3))
输出:
154977800
154977800
138660424
138660424
8791557861120
8791557861152
8791557861120
8791557861120
可见,可变对象每次创建时都会创建一个新的对象,随后发生改变会影响所有指向它的变量
1 test=[1] 2 def change1(a): 3 a = [2] 4 print(id(a)) 5 def change2(a): 6 a.append(3) 7 print(id(a)) 8 print(id(test)) 9 change1(test) 10 change2(test) 11 print(test)
输出:
154977800
128902536
154977800
[1, 3]
第一个函数是重新赋值,第二个函数是改变原对象的值自建对象属于可变对象
1 class Dog(): 2 def __init__(self,name,age): 3 self.name = name 4 self.age = age 5 6 dog1 = Dog('Sam',2) 7 print(id(dog1)) 8 dog2 = Dog('Tom',1) 9 print(id(dog2)) 10 dog1.name = 'Petter' 11 print(id(dog1))
输出:
155199584
155198408
155199584
自建对象属于可变对象
参考: