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

变量不是盒子,它是对象的标识

  - 标识、相等性和别名

charles = {'name':'Chales L.Dogson','born':1832}

lewis = charles

alex = {'name':'Chales L.Dogson','born':1832}

# lewis是charles的别名,is比较的是两个对象的id
print('charles is lewis:',charles is lewis)

# alex标识的对象和charles不同
print('charles is alex:',charles is alex)

# 但它们的值相等,'=='是语法糖,事实上调用的是__eq__
# dict对'=='进行了重载,比较的是对象的内容
print('charles == alex:',charles == alex)

输出:
charles is lewis: True
charles is alex: False
charles == alex: True

 

复制

  - 复制列表或多数内置可变集合,最简单的方式是使用内置的类型构造方法

  - 默认是浅复制

l1 = [3,[55,44],(7,8,9)]

l2 = list(l1)

# 复制之后,l2和l1内容相同
print('l2==l1:',l2 == l1)
# 但指向不同对象
print('l2 is l1:',l2 is l1)

# 但它们内部的元素仍然是同一个对象
print('l2[1] is l1[1]:',l2[1] is l1[1])

# 根据内部元素不同,将会产生不同表现
# 可变元素会相互影响
l1[1].append(33)
print('after l1[1] append:')
print('l1:',l1)
print('l2:',l2)

# 不可变元素不会互相影响
l1[2] += (10,)
print('after l1[2] append:')
print('l1:',l1)
print('l2:',l2)

输出:
l2==l1: True
l2 is l1: False
l2[1] is l1[1]: True
after l1[1] append:
l1: [3, [55, 44, 33], (7, 8, 9)]
l2: [3, [55, 44, 33], (7, 8, 9)]
after l1[2] append:
l1: [3, [55, 44, 33], (7, 8, 9, 10)]
l2: [3, [55, 44, 33], (7, 8, 9)]

   - 深复制需要用到copy.deepcopy

from copy import deepcopy

l1 = [3,[55,44],(7,8,9)]

l2 = deepcopy(l1)

# 内部的元素不再是同一个对象
print('l2[1] is l1[1]:',l2[1] is l1[1])


# 无论可变还是不可变元素,都不会相互影响
l1[1].append(33)
print('after l1[1] append:')
print('l1:',l1)
print('l2:',l2)

l1[2] += (10,)
print('after l1[2] append:')
print('l1:',l1)
print('l2:',l2)

输出:
l2[1] is l1[1]: False
after l1[1] append:
l1: [3, [55, 44, 33], (7, 8, 9)]
l2: [3, [55, 44], (7, 8, 9)]
after l1[2] append:
l1: [3, [55, 44, 33], (7, 8, 9, 10)]
l2: [3, [55, 44], (7, 8, 9)]

 

WeakValueDictionary

import weakref


class Dog:

    def __init__(self,name):

        self.name = name

    def __repr__(self):
        return 'Dog(%s)' % self.name


# stock保存一个弱引用的可变映射
stock = weakref.WeakValueDictionary()

catalog = [Dog('Alen'),Dog('Bob'),Dog('Wendy')]

for dog in catalog:
    stock[dog.name] = dog

print(sorted(stock.keys()))

del catalog

# 其他Dog对象的引用都消失了,只剩下dog引用了Wendy
print(sorted(stock.keys()))

# 把dog删除,Wendy也消失了
del dog

print(sorted(stock.keys()))

输出:

['Alen', 'Bob', 'Wendy']
['Wendy']
[]

 

WeakKeyDictionary

 

import weakref


class Dog:

    def __init__(self,name):

        self.name = name

    def __repr__(self):
        return 'Dog(%s)' % self.name


# stock保存一个弱引用的可变映射
stock = weakref.WeakKeyDictionary()

catalog = [Dog('Alen'),Dog('Bob'),Dog('Wendy')]

# 和WeakValueDictionary不同,WeakKeyDictionary的键是被引用的对象
for dog in catalog:
    stock[dog] = dog.name

print([item.name for item in stock.keys()])

del catalog

# 其他Dog对象的引用都消失了,只剩下dog引用了Wendy
print([item.name for item in stock.keys()])

# 把dog删除,Wendy也消失了
del dog

print([item.name for item in stock.keys()])

输出:

['Alen', 'Bob', 'Wendy']
['Wendy']
[]

 

posted @ 2019-03-16 15:29  StackNeverOverFlow  阅读(187)  评论(0编辑  收藏  举报