使用形如[[False for _ in range(m)] for _ in range(n) ]
初始化
使用 [[False]*m]*n
table[0][1]=True
在两种情况下竟然完全不同
1
cosmic 2019-04-05 15:52:57 +08:00 via Android
第二种方法只是复制了第一行的 reference,是 shallow copy。参考 fluent Python
|
2
alvin666 2019-04-05 15:55:06 +08:00 via Android
楼上说的对,第二种只是引用对象而已
|
4
whoami9894 2019-04-05 17:30:31 +08:00 via Android
第二种方式初始化后里面四个 false 的地址都相同是同一个对象的引用,且布尔值是不可变对象所以你修改后会建立新的布尔值,这也是为什么修改第二个布尔值而第一个布尔值还是指向原先的 false。而 lst[0]本身是列表对象,所以修改 lst[0]会导致指向它的引用都会被修改。所以出现了[[0, 1], [0, 1]]这种情况
|
5
kidlj 2019-04-05 17:40:33 +08:00 via iPhone
|
6
shidenggui 2019-04-05 19:07:07 +08:00
最近在看 《 Python 源码剖析》
类似 [obj] * count 的表达式,编译成字节码之后为 ``` # 构建 [obj] 0 LOAD_GLOBAL 0 (obj) 2 BUILD_LIST 1 # 读取 count 4 LOAD_GLOBAL 1 (count) # 实现 [obj] * count 6 BINARY_MULTIPLY ``` 而 BINARY_MULTIPLY 指令在源码中的实现为 ``` TARGET(BINARY_MULTIPLY) { PyObject *right = POP(); # 获取 count PyObject *left = TOP(); # 获取 [obj] # 获取相乘的结果 PyObject *res = PyNumber_Multiply(left, right); Py_DECREF(left); Py_DECREF(right); SET_TOP(res); if (res == NULL) goto error; DISPATCH(); } ``` 而 PyNumber_Multiply 最后调用的是 ->ob_type->tp_as_sequence->sq_repeat 函数, ``` # repeatfunc = sq_repeat # seq = [obj] # count = count return (*repeatfunc)(seq, count); ``` 该函数在 list 类型的实现为 ``` static PySequenceMethods list_as_sequence = { ... (ssizeargfunc)list_repeat, /* sq_repeat */ ... }; ``` 下面是 list_repeat 简化后的代码 ```c static PyObject * list_repeat(PyListObject *a, Py_ssize_t n) { ... PyObject *elem; # np 指向新分配的 count 大小的 list 对象 np = (PyListObject *) PyList_New(size); items = np->ob_item; # 如果 [obj] 的对象大小为 1 的话,我们这里就是如此 if (Py_SIZE(a) == 1) { # 获取 obj,即这里的 elem elem = a->ob_item[0]; for (i = 0; i < n; i++) { # 因为 elem 是指针,所以这里新的 list 的 items 里面包含的是原有的 obj 的引用,而不是复制 items[i] = elem; Py_INCREF(elem); } return (PyObject *) np; } ... } ``` 所以 [obj] * count 最后获得是包含 count 个 obj 引用的新 list 在 github 上写了一篇 blog,更加详细的论述了这个问题,有兴趣的可以点击观看 https://github.com/shidenggui/blog/issues/16 |
7
shidenggui 2019-04-05 19:08:54 +08:00
发现 v 站代码格式都混乱了,推荐去上条回复中的 github 链接查看
|
8
kmahyyg 2019-04-06 12:07:44 +08:00 via iPad
浅拷贝问题 这是新手都会踩的坑, 我猜楼主没有看官方 docs, 官方 docs 里的 best practice 里特别说了这个地方
|