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
vainly
V2EX  ›  Python

Python [0] * n 描述的意思是?

  •  
  •   vainly · 2017-04-28 10:59:00 +08:00 · 3965 次点击
    这是一个创建于 2795 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,为何结果是[0,0,0,0,0,0,0,0,0]

    11 条回复    2017-04-28 14:44:25 +08:00
    SakuraSa
        1
    SakuraSa  
       2017-04-28 11:10:53 +08:00   ❤️ 1
    list * int 意思是将数组重复 int 次并依次连接形成一个新数组
    guyskk
        2
    guyskk  
       2017-04-28 11:14:19 +08:00   ❤️ 1
    提醒一下有个坑:
    >>> items = [{}] * 10
    >>> items[0]['key'] = 'value'
    >>> print(items)
    vainly
        3
    vainly  
    OP
       2017-04-28 11:19:47 +08:00
    @SakuraSa
    @guyskk
    谢谢两位
    xiadd
        4
    xiadd  
       2017-04-28 11:21:30 +08:00
    @guyskk 感觉不是坑 是很正常的对象引用 原对象变化了 引用的对象自然发生了变化 js 里这种情况才是常态 当然我 python 不是很熟
    guyskk
        5
    guyskk  
       2017-04-28 11:30:33 +08:00
    @xiadd #4
    有一次我这样初始化一个列表:
    items = [{} for i in range(10)]
    然后发现貌似可以这样写:
    items = [{}] * 10
    结果出现很诡异的 Bug,印象深刻
    AZLisme
        6
    AZLisme  
       2017-04-28 11:40:30 +08:00
    这个很正常,Mutable 对象都是按引用传递的:
    a = {}
    b = a
    a['1'] = 1
    print(b)

    跟这个是一个道理。
    同理还有定义函数的时候:

    def foo(bar=[]):
    bar.append(1)
    print(bar)
    foo()
    foo()

    bar 这个默认参数是会改变的,因为默认参数的值也是对该数组的引用
    imn1
        7
    imn1  
       2017-04-28 11:45:08 +08:00
    @guyskk
    应该这样写
    items[0] = {'key':'value'}
    NoAnyLove
        8
    NoAnyLove  
       2017-04-28 13:25:09 +08:00   ❤️ 2
    相当于初始化一个长度为 n,每个元素的初始值都是 0 的`list`。貌似这是 Python 初始化 /预分配有较多元素的`list`的常用做法,貌似也是唯一的做法(有知道其他做法的朋友请分享一下)。

    感觉上等同于 C++的

    ```
    vector<int> tmp(n, 0)
    ```

    (但其实我不了解 C++的标准库,不知道说得对不对)

    正如 2L 所说,需要注意,如果要初始化的`list`中的的元素是其他 container 类型(比如`list`、`set`、`dict`等,但不包括`tuple`,`tuple`本身是不可变的,不实用于这里),因为 Python 中所有东西都是类的概念,变量其实类似于 Java/C++中的引用变量。如果要初始化一个 10*10 全是 0 的二位数组,所以如果按照

    ```
    l = [[0] * 10] * 10
    l[0][0]=1
    print(l)
    ```

    来初始化一个 2 维的`list`,你会“惊喜”地发现`l`中的每个元素都是指向同一个`list`对象。所以正确的做法是:

    ```
    l = [[0] * 10 for _ in range(10)]
    ```

    说到这里,真心想给《 Fluent Python 》打个广告,这个问题和之前看到的另外一个对`tuple`进行`+=`操作的问题,其实都在《 Fluent Python 》中有详细讲解,看完之后有种恍然大悟的感觉。。。。。。然而我还没看完。。。。。。貌似最近中文翻译版也要发布了
    KIDJourney
        9
    KIDJourney  
       2017-04-28 13:47:07 +08:00
    @guyskk 这个主要是 mutable 复制时的问题吧。
    guyskk
        10
    guyskk  
       2017-04-28 14:01:59 +08:00
    @KIDJourney #9 这里不是复制,list 里面的元素都是同一个对象。mutable 对象复制应该是 copy 和 deepcopy 的问题。
    llb123
        11
    llb123  
       2017-04-28 14:44:25 +08:00
    @guyskk #2 浅拷贝
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1034 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 23:12 · PVG 07:12 · LAX 15:12 · JFK 18:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.