6.对象引用、可变性和垃圾回收

1. python中的变量是什么?

python和java的变量本质不一样, python的变量实质上是一个指针 类似便利贴

便利贴过程:

a = 1
# 1.先在内存中生成好了1 
# 2.a贴在1上面

代码举例:

>>> a = [1, 2, 3]
>>> b = a
>>> print(id(a), id(b))
4329385544 4329385544

>>> print(a is b)
True

2. ==和is的区别

以代码说明:

>>> a = [1, 2, 3, 4]
>>> b = [1, 2, 3, 4]

>>> print(a == b)   # ==其实是调用了__eq__魔法函数
True

>>> print(id(a), id(b))
4400893512 4400893640
>>> print(a is b)   # is判断的是  内存是不是同一地址
False

# 证明   python中是唯一的
>>> class People:
>>>     pass

>>> person = People()
>>> if type(person) is People:
>>>     print('type(person) is People')   
type(person) is People

3. del语句和垃圾回收

python中的垃圾回收是 采用引用技术,当引用计数器为0时,才会删除
>>> a = 1   # 引用计数器为1
>>> b = a   # 引用计数器加1
>>> del a   # 引用计数器减1

>>> print(b)   # del a b依然存在
1

>>> print(a)
Traceback (most recent call last):
  File "6_what_is_var/3_delete.py", line 7, in <module>
    print(a)
NameError: name 'a' is not defined
通魔法函数__del__ 可以自定义 类在被回收时,需要做什么
>>> class A:
>>>     def __del__(self):
>>>         print('__del__ here')

>>> a = A()
>>> del(a)   #  del a
__del__ here

3. 一类经典的list参数错误

代码举例1:

>>> def add(a, b):
>>>     a += b
>>>     return a
    
>>> if __name__ == '__main__':
>>>     a = 1
>>>     b = 2
>>>     c = add(a, b)
>>>     print(c)
3
>>>     print(a, b)
1 2

>>>     a = [1, 2]
>>>     b = [3, 4]
>>>     c = add(a, b)
>>>     print(c)
[1, 2, 3, 4]
>>>     print(a, b)    # 传入的参数类型是list时, a的值也改变了
[1, 2, 3, 4]  [3, 4]

>>>     a = (1, 2)
>>>     b = (3, 4)
>>>     c = add(a, b)
>>>     print(c)
(1, 2, 3, 4)
>>>     print(a, b)
(1, 2) (3, 4)

代码举例2:

>>> 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',['cannon1', 'cannon2'])
>>>     com1.add('cannon3')
>>>     com1.remove('cannon1')
>>>     print(com1.staffs)
['cannon2', 'cannon3']

>>>     com2 = Company('com2')
>>>     com2.add('cannon4')

>>>     com3 = Company('com3')
>>>     com3.add('cannon5')

>>>     print(com2.staffs)     # com2  com3 使用了默认的staffs  得到了一样的staffs
['cannon4', 'cannon5']
>>>     print(com3.staffs)
['cannon4', 'cannon5']

>>>     print(com2.staffs is com3.staffs)   # com2  com3 没传入staffs 默认[]com2 com3共用了
True

    # 我们可以直接用类 名获取默认的[]
>>>     print(Company.__init__.__defaults__)
(['cannon4', 'cannon5'],)

结论:

  • 为避免以上出现的错误,我应尽量不使用list作为传入参数。即使不得已使用了,也要做好传入参数本身会被改变的准备。

猜你喜欢

转载自blog.csdn.net/weixin_41207499/article/details/80548746