self.agent_stats = [[0, 0, 0] for a in self.agents]
在阅读别人代码的时候看见的,请问这是什么意思?
1
mgna17 2016-08-22 20:03:25 +08:00 via Android 1
等号右边返回一个长度与 self.agents 相同的 list ,其中所有元素全是 [0, 0, 0]。
搜索关键字: python 列表生成式 |
2
TimePPT 2016-08-22 20:22:04 +08:00 via iPhone
self.agent_stats = []
for A in self.agent: self.agent_satats.apend([0, 0, 0]) |
7
introom 2016-08-22 21:20:58 +08:00 3
应该这样写, self.agent_stats = [ [0] * 3 for _ in range(len(self.agents))]
|
11
Jolly23 2016-08-23 01:22:05 +08:00 via iPhone
类似其他语言的二维数组
|
13
josephshen 2016-08-23 02:26:28 +08:00 via iPhone
半夜一觉睡醒了,我可以负责任的对你们说,乘号的写法是错误的,你们试试用一下 id 求一下 list 里面的数据,比较一下值是多少
|
14
Sylv 2016-08-23 03:13:41 +08:00 via iPhone
|
15
introom 2016-08-23 06:40:50 +08:00 6
这个算是新手的常见问题吧,我上个礼拜刚给别人解答过。把上次写的直接粘贴复制过来。
>>>> 我补充一下, list 的乘法是浅拷贝,只是复制存储的 PyObject*指针, 所以 a = [[]]*2 ,如果 a[0].append(3), 就会得到[[3], [3]] 而不是[[3], []] 至于为什么这种效果,没办法,人家就是这样设计的,参见 https://hg.python.org/cpython/file/8f84942a0e40/Objects/abstract.c#l928 上面会调用 list 的 sq_repeat , 也就是在这里, https://hg.python.org/cpython/file/db93af6080e7/Objects/listobject.c#l539 你看,它只是复制了指针。 其实我想补充的是, 对于 python 的多维数组,请不要这样写, [[0 for i in xrange(4)] for j in xrange(4)], 既然 0 是 immutable ,你完全可以这样写 [[0]*4 for j in xrange(4)] 但是,注意到你都用不到 j 这个变量,我发现你用的是 python2, 在 python2 里, list comprehension 没有新开栈帧,用的是当前函数(或者 module,本质上是 PyFrame)的 local namespace, 换句话说,你这个 j 除了污染当前函数的 local 名字空间以外,别无是处。 建议这样写, [[0]*4 for _ in xrange(4)] 当然,在 Python3 里, list comphrension 会在一个新的 frame 里执行,不会存在名字空间的污染,不过还是推荐写成_, 因为你根本用不到 j 这个变量。 |
16
maowu 2016-08-23 09:12:21 +08:00 via Android
@josephshen 能否说明一下为什么错了?
|
17
KingHL 2016-08-23 09:59:58 +08:00
楼上已经有人解释的很好了。个人理解, 对于 mutable 对象来说, 用*是不对的, 因为所有的变量名都会指向同一个值,此值改变了,所有的变量都会变。对于 immutable 对象,虽然所有变量名指也向同一个值,但是在改变值的时候,因为原值是 immutable 的,所以被改变的变量名会解引用,重新指向新值的引用,也就不会出问题了。解释的有点不清楚,建议查资料理解下 python 的对象和命名空间的区别。
|
18
bravecarrot 2016-08-23 10:07:42 +08:00
@introom 感谢。之前看到过,结果没记住,昨天还刚刚这样用了呢。还有, _ is really a good name.
|
19
hitmanx 2016-08-23 11:34:10 +08:00
python 里一直让我比较困惑的就是引用、浅拷贝、深拷贝,可能也和我之前一直用 c/c++有关系。在 c/c++里是按值或按引用 /指针传递,在大部分的情况下是很容易确定的,而且是确定无疑的。在 python 里,我能理解比如最常见的场景: mutable,immutable 涉及到拷贝时产生的状况,但是[[0] * 3] * n 这种情况下会发生什么情况,除了做个实验看一下 id ,我好像还真不敢直接下结论。你们都是怎么记忆的,除了 case by case 的记忆以外,有什么比较通用的规则吗?
|
21
cartmanie 2016-08-23 12:15:31 +08:00
>>> a=[1,2,3]
>>> b=[[0,0,0] for c in a] >>> print b [[0, 0, 0], [0, 0, 0], [0, 0, 0]] |
22
qnnnnez 2016-08-23 12:16:29 +08:00
|
23
shyling 2016-08-23 12:41:10 +08:00
你需要[([0]*3)[:] for _ in range(10)]
|
24
hitmanx 2016-08-23 14:20:15 +08:00
@qnnnnez 涉及到显式拷贝的比较好辨认,包括函数传参。但是像这个*,第一反应没想到是个拷贝动作。
如果在 c++里,给我的感觉可能类似 const size_t len = 5; std::vector<std::vector<int> > vec(len, std::vector<int>(3, 0)); |
29
gkiwi 2016-08-24 08:51:21 +08:00
@qnnnnez
你的姿势不对,后面的 b,c 引用的都是[0]这个 list 的地址,而 list 是 muatble 的; 你试试这个: a = 1 b = a, a, a, a, a c = [b] * 5 print(c) a = 2 print(c) http://blog.csdn.net/hsuxu/article/details/7785835 |
31
Yinz 2016-08-25 00:13:37 +08:00
学习了:D
|