Python 使用[:]列出作业
两者之间有什么区别Python 使用[:]列出作业,python,list,Python,List,两者之间有什么区别 list = range(100) 及 用Python 编辑 我应该提到的是,在此之前,分配列表变量已分配给列表: list = [1, 2, 3] list = range(100) 或 list[:]指定列表中的一个范围,在这种情况下,它定义列表的完整范围,即整个列表并对其进行更改列表=范围(100),另一方面,清除列表的原始内容并设置新内容 但请尝试以下方法: a=[1,2,3,4] a[0:2]=[5,6] a # prints [5,6,3,4] 你看,我
list = range(100)
及
用Python
编辑
我应该提到的是,在此之前,分配列表变量已分配给列表:
list = [1, 2, 3]
list = range(100)
或
list[:]
指定列表中的一个范围,在这种情况下,它定义列表的完整范围,即整个列表并对其进行更改<代码>列表=范围(100),另一方面,清除列表的原始内容并设置新内容
但请尝试以下方法:
a=[1,2,3,4]
a[0:2]=[5,6]
a # prints [5,6,3,4]
你看,我们用赋值改变了前两个元素。这意味着,使用这种表示法,您可以一次性更改列表中的几个元素
list[:] = range(100)
无法处理未初始化的变量,因为它正在修改它。
[:]
指定了整个列表。第一个列表重新定义了内置名称列表
以指向某个列表
第二个失败,出现
TypeError:“type”对象不支持项分配
列表[:]
仅当已经有一个名为列表
的对象允许片分配时才起作用
另外,您不应该给变量命名list
,因为有一个内置的名为list
的变量,它是list
类型本身
lst = anything
lst[:] = whatever
您将名称lst
指向一个对象。它不会以任何方式更改用于指向的旧对象lst
,但如果没有其他对象指向该对象,其引用计数将降至零,并将被删除
当你这样做的时候
lst = anything
lst[:] = whatever
您正在对任何对象进行迭代,创建一个中间元组,并将元组的每个项分配给已经存在的lst
对象中的索引。这意味着,如果多个名称指向同一对象,您将在引用任何名称时看到所反映的更改,就像使用附加
或扩展
或任何其他就地操作一样
区别的一个例子是:
>>> lst = range(1, 4)
>>> id(lst)
74339392
>>> lst = [1, 2, 3]
>>> id(lst) # different; you pointed lst at a new object
73087936
>>> lst[:] = range(1, 4)
>>> id(lst) # the same, you iterated over the list returned by range
73087936
>>> lst = xrange(1, 4)
>>> lst
xrange(1, 4) # not a list, an xrange object
>>> id(lst) # and different
73955976
>>> lst = [1, 2, 3]
>>> id(lst) # again different
73105320
>>> lst[:] = xrange(1, 4) # this gets read temporarily into a tuple
>>> id(lst) # the same, because you iterated over the xrange
73105320
>>> lst # and still a list
[1, 2, 3]
在速度方面,切片分配较慢。有关其内存使用情况的更多信息,请参阅。[:]对于制作列表的深度副本也很有用
def x(l):
f=l[:]
g=l
l.append(8)
print "l", l
print "g", g
print "f", f
l = range(3)
print l
#[0, 1, 2]
x(l)
#l [0, 1, 2, 8]
#g [0, 1, 2, 8]
#f [0, 1, 2]
print l
#[0, 1, 2, 8]
对l的修改反映在g中(因为,它们都指向同一个列表,事实上,g和l在python中都只是名称),而不是f中(因为它是l的副本)
但是,对你来说,这没什么区别。(不过,我没有资格评论这两种方法的内存使用情况。)
编辑
h = range(3)
id(h) #141312204
h[:]=range(3)
id(h) #141312204
h=range(3)
id(h) #141312588
列表[:]=范围(100)更新列表
列表=范围(100)创建新列表
@agf:感谢您指出我的错误这与我在回答中提到的意思相同。我理解如何使用slice来更改列表的一部分,但我很好奇在操作整个列表时是否有任何差异。更改元素和擦除内容之间有什么区别?是否存在性能或内存使用差异?list=range(100)
不会删除任何内容的原始内容。它只是指向一些不同的东西。list
。区别不仅仅是一个要求列表已经存在的东西。请看我对Michael答案的评论,还有更多。如果已经有一个名为list
的变量,这显然就是他的意思,那就不是了。还要注意id(list[:])
与id(list)
不同,并且随着每次调用而变化。@分配左侧的rplnt切片与分配右侧/未分配的rplnt切片不同;正常的切片复制实际上与这个问题无关。[:]
不会制作深度复制,而是制作浅层复制。另外,切片分配(分配左侧切片)与正常切片(分配右侧切片/不分配)完全不同。它根本不创建副本。h=range(3),id(h)#141312204 h[:]=range(3),id(h)#141312204 h=range(3),id(h)#141312588 list[:]=range(100)更新list list=range(100)创建新列表@agf:谢谢你指出我的错误。更具体地说,list[:]=range(100)
创建一个没有名称的新列表,然后从中更新list
。两个列表存在一段时间list[:]=xrange(100)
创建一个新的xrange
迭代器并从中更新列表,无需中间存储list=range(100)
创建一个新列表,将名称list
指向该列表,如果没有其他内容指向该列表,则可以删除旧列表,因为它不再有名称。请看我的答案,以获得更完整的描述。请谈谈你使用哪一个的时间是重要的-你的例子没有显示这两个将有不同的影响,除了微小的速度差异。i、 e.l=[1,2,3];l2=l
-现在通过l=
分配只会更改ll[:]=
也会导致l2发生变化,因为它们指向的是同一个列表,该列表已发生变化。@Aaron我确实说过这一点;请看我答案的第一段。“您将名称lst指向一个对象。它不会以任何方式更改lst用于指向的旧对象,尽管如果没有其他对象指向该对象,其引用计数将降至零,并将被删除。”我补充道“这意味着,如果多个名称指向同一个对象,您将在引用任何名称时看到所反映的更改。“还有一点关于切片分配的内容,因此相反的内容是明确的。我记得,而且我怀念那些日子,那时我不必考虑range
和xrange
之间的区别,切片分配(x[:]
)永远不会进入我的头脑+感谢你提醒我那些我一直试图忘记的内在的东西。