代码之家  ›  专栏  ›  技术社区  ›  peter.petrov

python slice[:]行为不一致

  •  1
  • peter.petrov  · 技术社区  · 7 年前

    在python中,为什么[:]切片操作的行为不一致?
    它对列表和字符串的行为不同。

    对于列表,它提供一个复制列表对象;对于字符串,它提供相同的字符串对象。

    我觉得这让人困惑,违反直觉。有什么办法解释/证明这一点吗?

        >>> s = "1234"
        >>> s is (s[:2] + s[2:])
        False
        >>> s is s[:]
        True
        >>> lst = [1,2,3,4]
        >>> lst is lst[:]
        False
        >>> lst is (lst[:2] + lst[2:])
        False
    

    我觉得这部分令人困惑。我希望这个能回来 False .

    >>> s is s[:]
    True
    

    另外,我希望这两个返回相同的结果 假 但事实并非如此。

    >>> s is (s[:2] + s[2:])
    False
    >>> s is s[:]
    True
    

    有什么想法吗?

    2 回复  |  直到 7 年前
        1
  •  3
  •   user2357112    7 年前

    对于大多数内置类型,python试图确保切片的(浅)突变不会影响切片所来自的对象。

    对于列表,这需要一个副本或变异 l[:] 会变异 l .

    对于字符串,字符串不支持突变,因此语句如“mutating” s[:] 不影响 s “即使是 s[:] is s . 不需要复制,因此为了节省时间和内存,实现不需要复制。这是一个实现细节,而不是语言保证;复制一个实现是完全有效的。

    (你可能认为实习是有关系的,但事实并非如此。这个对象重用优化与Interning完全无关。这种情况甚至发生在非内部字符串上。你可以看看 the implementation 如果你愿意的话。


    一般来说,如果您的程序曾经关心不可变对象的身份,那么您可能做了一些错误的事情。对象标识对于可变对象很重要,而Python确保可以预测可变对象的标识。对于不可变的对象,对象标识几乎不重要,而Python应用了许多对象重用实现,这些实现打破了许多关于对象标识的乐观假设。

        2
  •  0
  •   Kirk Strauser    7 年前

    短字符串是 interned 这样一百万个“测试”实例就不会占用一百万个字符串的存储空间。这是安全的,因为python的字符串是不可变的:如果两个字符串一次相等,您可以保证它们在余生都是相等的。

    下面是另一个由相同的内存对象表示的短字符串示例:

    >>> a = 'foo'
    >>> b = 'foo'
    >>> a is b
    True