Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python切片[:]行为不一致_Python_Python 3.x_Slice - Fatal编程技术网

Python切片[:]行为不一致

Python切片[:]行为不一致,python,python-3.x,slice,Python,Python 3.x,Slice,在Python中,[:]切片操作的行为为何不一致? 对于列表和字符串,它的行为不同 对于列表,它给出一个复制列表对象;对于字符串,它给出相同的字符串对象 我发现这令人困惑,违反直觉。有没有办法解释/证明这一点 >>> s = "1234" >>> s is (s[:2] + s[2:]) False >>> s is s[:] True >>> lst = [1,2,3,4]

在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
另外,我希望这两个函数返回相同的结果
False
,但事实并非如此

>>> s is (s[:2] + s[2:])
False
>>> s is s[:]
True
有什么想法吗

短字符串是,因此一百万个“测试”实例不会占用一百万个字符串的存储空间。这是安全的,因为Python的字符串是不可变的:如果两个字符串一次相等,则可以保证它们在剩余的生命周期中相等

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

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

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

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

对于字符串,字符串不支持突变,因此“突变
s[:]
不影响
s
”这样的语句是空的,即使
s[:]是s
。无需制作副本,因此为了节省时间和内存,实现不制作副本。这是一个实现细节,不是语言保证;对于实现来说,制作一个副本是完全有效的

(您可能认为涉及到内部操作,但事实并非如此。此对象重用优化与内部操作完全无关。即使对于非内部操作的字符串,也会发生这种情况。如果需要,您可以查看一下。)



一般来说,如果您的程序关心不可变对象的标识,那么您可能做错了什么。对象标识对于可变对象很重要,Python确保可变对象的标识是可预测的。对于不可变的对象,对象标识无关紧要,Python应用了许多对象重用实现,打破了许多关于对象标识的乐观假设。

基本上,
interned
在Python中是不保证的。这意味着您不能期望相同的字符串指向同一个对象。@Sraw我的要求正好相反。如果您的程序关心不可变对象的标识,那么您可能做错了什么。对象标识对于可变对象很重要,但对于不可变对象,所有类型的对象重用优化都是安全的。@user2357112我明白了,但。。。嗯,这种行为似乎仍然不一致。为什么
s是s[:]
返回
True
。我觉得这很奇怪,是不是只有我?@peter.petrov这是一个实现细节,毫无疑问,
str
对象的“整片”经过优化,只返回
str
对象本身。为什么这很重要?虽然实习是一件事,但这里不涉及。(而且,Python的实习标准实际上并不涉及长度。)有多短?我刚刚尝试了一个200个字符的字符串,它仍然说
a是[:]
真的
。它涉及到
s[:]
是“制作s的副本”的简写,这是通过指针操作最有效地完成的
s[:2]+s[2:://code>的不同之处在于它是从片段构建一个字符串,即使结果碰巧已经在内存中,Python也很难在事后确定这一点。不过,我可能对字符串长度有点误解。