06-对象引用、可变性和垃圾回收
一、对象引用、可变性和垃圾回收
1.1、python中的变量是什么?
python和java中的变量本质不一样,java中的变量声明首先要声明变量类型(int\string),虚拟机就会在内存中申请空间,空间的大小和类型相关。java中的变量就像一个有大小的盒子一样。
然而python中的变量与java不一样,python的变量实质上是一个指针。
a = "cdas" #python变量 #上面是a指向cdas存储的地址 ,
1.2、is和==的区别
a = [1,2,3] b = [1,2,3] print(a is b) #False print(id(a),id(b)) #2497320800840 2497320801352 print(a == b) #True 当运行这个的时候会调用魔法函数__eq__,来判断两值是否相等 # ==是判断两个值是否相等,is是判断两个值的地址是否一样 a = 1 b = 1 print(a is b) #True print(a == b) #True print(id(a),id(b)) #140716358922496 140716358922496 # a = "abc" # b = "abc" # print(a is b)#True #当创建一个小整数的时候,python会在下次创建一样的小整数时,会引用同一对象
1.3、del语句和垃圾回收
#python中垃圾回收的算法是采用 引用计数 a = 1 #a=1 然后1的引用计数加一,b=1然后1的引用计数再加一,当删除a的时候, b = 1 #引用计数减一,当减到0的时候才会启用垃圾回收机制,然而c++ 是直接采用垃圾回收机制 del a print(b) #1 print(a)#NameError: name 'a' is not defined #如果我们要对我们的对象做垃圾回收机制的时候,我们就重载__del__魔法函数 class A: def __del__(self): pass
1.4、一个经典的参数错误
def add(a,b): a += b return a class Company: def __init__(self, name, staffs=[]): self.name = name self.staffs = staffs def add(self, staff_name): self.staffs.append(staff_name) def remove(self, staff_name): self.staffs.remove(staff_name) if __name__ == "__main__": com1 = Company("com1", ["lishuntao1", "lishuntao2"]) com1.add("lishuntao3") com1.remove("lishuntao1") print (com1.staffs) #['lishuntao2', 'lishuntao3'] com2 = Company("com2") com2.add("lishuntao") print(com2.staffs) #['lishuntao'] print (Company.__init__.__defaults__) #(['lishuntao'],) #结合下面注释的可以总结出,当传递一个列表的时候,可能会影响值的改变,在这里,com3与com2 #都没有传入值,则对象都采用默认值,因此值的改动会影响默认值的改变,因此以后出现这样的问题 #需要警惕这样的结果,才不会一头雾水。 com3 = Company("com3") com3.add("lishuntao5") print (com2.staffs) #['lishuntao', 'lishuntao5'] print (com3.staffs) #['lishuntao', 'lishuntao5'] print (com2.staffs is com3.staffs) #True # a = 1 # b = 2 # c = add(a,b) # print(a,b) #1 2 # print(c) #3 # # a = [1,2] # b = [3,4] # c = add(a, b) # print(a, b) #[1, 2, 3, 4] [3, 4] # print(c) #[1, 2, 3, 4] # # a = (1,2) # b = (3,4) # c = add(a, b) # print(a, b) #(1, 2) (3, 4) # print(c) #(1, 2, 3, 4)