实验1 列表中存的是什么?
- 输入
list1 = [coro1(), coro2()]
import sys
print("由两个协程对象构成的list1的占用字节是", sys.getsizeof(list1))
list2 = [1, 2]
print("由两个整型数字对象构成的list2的占用字节是", sys.getsizeof(list2))
list3 = []
print("空列表占用的字节是", sys.getsizeof(list3))
a = 1
print("数字1对象占用的字节是", sys.getsizeof(a))
b = coro1()
print("一个协程对象占用的字节是", sys.getsizeof(b))
print("由此可以知道64位系统上在列表中保存的是对象的64位引用地址,即8个字节")
- 输出
由两个协程对象构成的list1的占用字节是 80
由两个整型数字对象构成的list2的占用字节是 80
空列表占用的字节是 64
数字1占用的字节是 28
一个协程对象占用的字节是 88
由此可以知道64位系统上在列表中保存的是对象的64位引用地址,即8个字节
- 补充
-
80-64=16=8*2
,对应列表中是2个元素。 -
coro1
和coro2
都是协程函数,见附1。
-
实验2 在列表循环中对列表进行删除操作,会不会出错?
- 输入
list1 = [1, 2, 3]
for i in list1:
print("当前的i是", i)
print("当前循环中的列表是", list1)
list1.remove(i)
print('\n',"!!!输出结果怎么不对,WTF,why the failure!!!")
print("原来是python在for中使用了自己的计数器")
print("如果对列表使用深拷贝再循环就好了", '\n')
list1 = [1, 2, 3]
for i in list(list1):
print("当前的i是", i)
print("当前循环中的列表是", list1)
list1.remove(i)
- 输出
当前的i是 1
当前循环中的列表是 [1, 2, 3]
当前的i是 3
当前循环中的列表是 [2, 3]
!!!输出结果怎么不对,WTF,why the failure!!!
原来是python在for中使用了自己的计数器
*如果对列表使用深拷贝再循环就好了 *
当前的i是 1
当前循环中的列表是 [1, 2, 3]
当前的i是 2
当前循环中的列表是 [2, 3]
当前的i是 3
当前循环中的列表是 [3]
-
测试图
- 补充
Python在for循环中根据自己的计数器对列表进行索引,所以一开始会出现在第二次循环中i为3的现象。
实验3 列表深复制到底复制的是什么?
- 输入
list1 = [coro1(), coro2(), 1, 2] # 提醒,coro1()返回一个协程对象
print("初始列表list1是", list1)
list2 = list1
print("浅复制的列表list2是", list2)
list3 = list(list1)
print("深复制的列表list3是", list3)
print("可以看出打印的内容都是一样的,内存地址相同,数字相同。")
print("下面对列表进行操作")
list1.remove(list1[0])
print("删除操作后初始列表list1是", list1)
print("删除操作后浅复制的列表list2是", list2)
print("删除操作后深复制的列表list3是", list3)
print("可以看出浅复制的列表受到了影响,而深复制的列表并没有受到影响")
print("但是如果使用列表中的协程对象呢")
list1[0].send(None)
list3[1].send(None)
print("两者操作的是同一个协程对象!")
print("深复制仅仅是新建了一份列表,不会更深一层到新建一个协程对象,由于深复制列表中的元素(实际是引用对象地址)和旧列表中一致,操作的对象其实还是一样的,但对列表的增删改不同。")
- 输出
初始列表list1是 [<coroutine object coro1 at 0x0000000004309E08>, <coroutine object coro2 at 0x0000000004309F68>, 1, 2]
浅复制的列表list2是 [<coroutine object coro1 at 0x0000000004309E08>, <coroutine object coro2 at 0x0000000004309F68>, 1, 2]
深复制的列表list3是 [<coroutine object coro1 at 0x0000000004309E08>, <coroutine object coro2 at 0x0000000004309F68>, 1, 2]
可以看出打印的内容都是一样的,内存地址相同,数字相同。
下面对列表进行操作
删除操作后初始列表list1是 [<coroutine object coro2 at 0x0000000004309F68>, 1, 2]
删除操作后浅复制的列表list2是 [<coroutine object coro2 at 0x0000000004309F68>, 1, 2]
删除操作后深复制的列表list3是 [<coroutine object coro1 at 0x0000000004309E08>, <coroutine object coro2 at 0x0000000004309F68>, 1, 2]
可以看出浅复制的列表受到了影响,而深复制的列表并没有受到影响
但是如果使用列表中的协程对象呢
C2: Start
C2: a
两者操作的是同一个协程对象!
深复制仅仅是新建了一份列表,不会更深一层到新建一个协程对象,由于深复制列表中的元素(实际是引用对象地址)和旧列表中一致,操作的对象其实还是一样的,但对列表的增删改不同。
- 补充
在复制由协程构成的列表时,我对深复制的概念产生了疑惑,以为深复制会产生新的协程,其实是协程对象在使用协程函数的时候产生,深复制就是对其引用地址的复制,并不改变协程本身。对于其他类型的对象也是一样的。
附1
from types import coroutine
# 通过装饰器产生基于生成器的协程对象
@coroutine
def switch():
yield
#python3.5实现的特性,参见PEP-0492
async def coro1():
print("C1: Start")
await switch()
print("C1: Stop")
async def coro2():
print("C2: Start")
await switch()
print("C2: a")
await switch()
print("C2: Stop")