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

python 有切片引用类型吗?

  •  
  •   ryanking8215 ·
    ryanking8215 · 2015-01-05 16:30:24 +08:00 · 3626 次点击
    这是一个创建于 3644 天前的主题,其中的信息可能已经有所发展或是发生改变。
    a=[1,2,3,4,5]
    b=a[1:2]
    b[0] = 5 # b是a[1:2]切片的浅拷贝,a的值不变

    有没有切片引用类型呢?
    比如nodejs:
    buf = buf.slice(offset)
    10 条回复    2015-01-07 14:46:47 +08:00
    limbo0
        1
    limbo0  
       2015-01-05 16:37:26 +08:00
    浅拷贝是会变吧,深拷贝不会变

    没见过切片引用的~~
    fdb713
        2
    fdb713  
       2015-01-05 16:39:25 +08:00
    直接
    a[1:2] = [5]
    不就可以达到
    a == [1,2,3,4,5]的效果了么。。。
    fdb713
        3
    fdb713  
       2015-01-05 16:41:03 +08:00
    @fdb713 打错了 a == [1, 5, 3, 4, 5]
    你甚至可以
    a=[1,2,3,4,5,6,7]
    a[::2] = [2,4,6,8]

    a就直接为 [2, 2, 4, 4, 6, 6, 8] 了
    hahastudio
        4
    hahastudio  
       2015-01-05 17:13:51 +08:00   ❤️ 1
    先说一下,很多人可能会误解,实际 Python 的运行效果是这样的:
    >>> a = [1,2,3,4,5]
    >>> b = a[1:2]
    >>> b
    [2]
    >>> b[0]=5
    >>> b
    [5]
    >>> a
    [1, 2, 3, 4, 5]

    很遗憾,Python 的序列切片一定是复制的,所以实际没有切片引用类型
    这也就是为什么会有一个深度复制 list 的 trick 是 b = a[:]

    你想要的效果只能迂回地获得。

    如果你知道 a[1:2] 其实是 a[slice(1,2)] 的话
    你可以传两个参数,就像是当初 C++ 传数组似的:

    def foo(array, slc):
    ....array[slc] = [5]

    >>> foo(a, slice(1,2))
    >>> a
    [1, 5, 3, 4, 5]
    ryanking8215
        5
    ryanking8215  
    OP
       2015-01-05 17:40:54 +08:00
    @hahastudio 谢谢,明白了
    ruoyu0088
        6
    ruoyu0088  
       2015-01-05 18:42:37 +08:00
    有啊,NumPy的数组。
    yegle
        7
    yegle  
       2015-01-07 05:32:15 +08:00
    slice是复制不是引用也不一定是坏事…写Golang经常没转过弯来…

    至于想做切片引用…写个class包装一下不就好了…为什么一定要语言内置呢…

    https://gist.github.com/yegle/af51f08ef289bdffbc7f
    hahastudio
        8
    hahastudio  
       2015-01-07 11:21:03 +08:00
    @yegle 大大我们的 Python 是不是不在同一个位面上= =

    我用的是 2.7.8,其实您这个方案跟普通的是没有区别的= =
    >>> l = [1, 2, 3, 4]
    >>> l[0] = 999
    >>> l
    [999, 2, 3, 4]
    >>> l = [1, 2, 3, 4]
    >>> ref_copy = MyList(l)
    >>> def foo(ref_l):
    ....ref_l = [999]

    >>> foo(ref_copy[0])
    >>> l
    [1, 2, 3, 4]

    然后 2.7.8 并没有抛弃 __getslice__ 和 __setslice__
    >>> ref_copy[1:3]
    []
    yegle
        9
    yegle  
       2015-01-07 14:46:02 +08:00   ❤️ 1
    @hahastudio 我在3.4上测试的,更新了gist你可以参考下。

    和你的代码里不同的一点是,Python里assignment是没有magic method可以用来重载的,所以你的代码里foo函数对ref_l进行赋值是不会修改原list的,只能用ref_l[:] = [999]的方式进行修改。

    所谓的『引用类型』就是一个普通list基础上对start/stop range进行操作而已…这个和Golang里的slice(变长数组)实现上是一样的。
    yegle
        10
    yegle  
       2015-01-07 14:46:47 +08:00
    __setitem__可能还需要修改,我懒得做了,明白意思就好了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2689 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 04:03 · PVG 12:03 · LAX 20:03 · JFK 23:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.