如何理解这一句 Python 的赋值语句? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
jmyz0455
V2EX    Python

如何理解这一句 Python 的赋值语句?

  •  
  •   jmyz0455 2016 年 8 月 22 日 5312 次点击
    这是一个创建于 3448 天前的主题,其中的信息可能已经有所发展或是发生改变。

    self.agent_stats = [[0, 0, 0] for a in self.agents]

    在阅读别人代码的时候看见的,请问这是什么意思?

    31 条回复    2016-08-25 00:13:37 +08:00
    mgna17
        1
    mgna17  
       2016 年 8 月 22 日 via Android   1
    等号右边返回一个长度与 self.agents 相同的 list ,其中所有元素全是 [0, 0, 0]。
    搜索关键字: python 列表生成式
    TimePPT
        2
    TimePPT  
    PRO
       2016 年 8 月 22 日 via iPhone
    self.agent_stats = []

    for A in self.agent:
    self.agent_satats.apend([0, 0, 0])
    TimePPT
        3
    TimePPT  
    PRO
       2016 年 8 月 22 日 via iPhone
    @TimePPT for 循环第二行有缩进
    TimePPT
        4
    TimePPT  
    PRO
       2016 年 8 月 22 日 via iPhone
    @TimePPT for a in self.agent

    手机码字真费劲
    jmyz0455
        5
    jmyz0455  
    OP
       2016 年 8 月 22 日
    @mgna17 感谢关键词,很多不会的地方都是因为连关键词都想不出来
    jmyz0455
        6
    jmyz0455  
    OP
       2016 年 8 月 22 日
    @TimePPT 没关系,看懂了,谢谢
    introom
        7
    introom  
       2016 年 8 月 22 日   3
    应该这样写, self.agent_stats = [ [0] * 3 for _ in range(len(self.agents))]
    mingyun
        8
    mingyun  
       2016 年 8 月 22 日
    @introom 有什么区别吗
    ericls
        9
    ericls  
       2016 年 8 月 22 日 via iPhone
    @mingyun 他这个写法很 pythonic
    msg7086
        10
    msg7086  
       2016 年 8 月 23 日
    @ericls 比起 [[0] * 3] * len(self.agents) 有什么优势?
    Jolly23
        11
    Jolly23  
       2016 年 8 月 23 日 via iPhone
    类似其他语言的二维数组
    ericls
        12
    ericls  
       2016 年 8 月 23 日
    @msg7086 你这个写法更好
    josephshen
        13
    josephshen  
       2016 年 8 月 23 日 via iPhone
    半夜一觉睡醒了,我可以负责任的对你们说,乘号的写法是错误的,你们试试用一下 id 求一下 list 里面的数据,比较一下值是多少
    introom
        15
    introom  
       2016 年 8 月 23 日   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 这个变量。
    maowu
        16
    maowu  
       2016 年 8 月 23 日 via Android
    @josephshen 能否说明一下为什么错了?
    KingHL
        17
    KingHL  
       2016 年 8 月 23 日
    楼上已经有人解释的很好了。个人理解, 对于 mutable 对象来说, 用*是不对的, 因为所有的变量名都会指向同一个值,此值改变了,所有的变量都会变。对于 immutable 对象,虽然所有变量名指也向同一个值,但是在改变值的时候,因为原值是 immutable 的,所以被改变的变量名会解引用,重新指向新值的引用,也就不会出问题了。解释的有点不清楚,建议查资料理解下 python 的对象和命名空间的区别。
    bravecarrot
        18
    bravecarrot  
       2016 年 8 月 23 日
    @introom 感谢。之前看到过,结果没记住,昨天还刚刚这样用了呢。还有, _ is really a good name.
    hitmanx
        19
    hitmanx  
       2016 年 8 月 23 日
    python 里一直让我比较困惑的就是引用、浅拷贝、深拷贝,可能也和我之前一直用 c/c++有关系。在 c/c++里是按值或按引用 /指针传递,在大部分的情况下是很容易确定的,而且是确定无疑的。在 python 里,我能理解比如最常见的场景: mutable,immutable 涉及到拷贝时产生的状况,但是[[0] * 3] * n 这种情况下会发生什么情况,除了做个实验看一下 id ,我好像还真不敢直接下结论。你们都是怎么记忆的,除了 case by case 的记忆以外,有什么比较通用的规则吗?
    qnnnnez
        20
    qnnnnez  
       2016 年 8 月 23 日 via Android
    @hitmanx 全部看成传引用就行了,没有隐式拷贝
    cartmanie
        21
    cartmanie  
       2016 年 8 月 23 日
    >>> a=[1,2,3]
    >>> b=[[0,0,0] for c in a]
    >>> print b
    [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
    qnnnnez
        22
    qnnnnez  
       2016 年 8 月 23 日
    @introom 反对,和是不是 immutable 没有关系

    a = [1]
    b = a, a, a, a, a
    c = [b] * 5
    print(c)
    a[0] = 2
    print(c)
    shyling
        23
    shyling  
       2016 年 8 月 23 日
    你需要[([0]*3)[:] for _ in range(10)]
    hitmanx
        24
    hitmanx  
       2016 年 8 月 23 日
    @qnnnnez 涉及到显式拷贝的比较好辨认,包括函数传参。但是像这个*,第一反应没想到是个拷贝动作。

    如果在 c++里,给我的感觉可能类似
    const size_t len = 5;
    std::vector<std::vector<int> > vec(len, std::vector<int>(3, 0));
    allanzyne
        25
    allanzyne  
       2016 年 8 月 23 日 via Android
    @shyling [:] 没有必要吧?
    shyling
        26
    shyling  
       2016 年 8 月 23 日
    @allanzyne 需要 0 0
    allanzyne
        27
    allanzyne  
       2016 年 8 月 23 日 via Android
    @shyling 我测了一下,好像和没写一样啊?
    shyling
        28
    shyling  
       2016 年 8 月 23 日
    @allanzyne 哦,不需要,记错了
    gkiwi
        29
    gkiwi  
       2016 年 8 月 24 日
    @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
    qnnnnez
        30
    qnnnnez  
       2016 年 8 月 24 日
    @gkiwi 仔细想想,我发现应该是“不包含 mutable 对象的 immutable 对象”
    Yinz
        31
    Yinz  
       2016 年 8 月 25 日
    学习了:D
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2319 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 07:09 PVG 15:09 LAX 23:09 JFK 02:09
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86