Назначение списка с помощью [:]
Какая разница между
list = range(100)
и
list[:] = range(100)
в Python?
ИЗМЕНИТЬ
Я должен был упомянуть, что до того, как эта переменная списка назначений была уже назначена списку:
list = [1, 2, 3]
list = range(100)
или
list = [1, 2, 3]
list[:] = range(100)
Ответы
Ответ 1
Когда вы делаете
lst = anything
Вы указываете имя lst
на объект. Он не меняет старый объект lst
, который используется для указания на него каким-либо образом, хотя если ничто иное не указывает на этот объект, его счетчик ссылок упадет до нуля, и он будет удален.
Когда вы делаете
lst[:] = whatever
Вы повторяете whatever
, создавая промежуточный кортеж и присваивая каждому элементу кортежа индекс в уже существующем объекте lst
. Это означает, что если несколько имен указывают на один и тот же объект, вы увидите, что изменение отразилось при ссылке на любое из имен, как если бы вы использовали append
или extend
или любые другие операции на месте.
Пример разницы:
>>> 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]
Когда дело доходит до скорости, назначение срезов происходит медленнее. См. Использование памяти назначения фрагментов Python для получения дополнительной информации об использовании памяти.
Ответ 2
Первая переопределяет встроенное имя list
, чтобы указать на некоторый список.
Второе не выполняется с TypeError: 'type' object does not support item assignment
.
Ответ 3
list[:]
указывает диапазон внутри списка, в этом случае он определяет полный диапазон списка, т.е. весь список и изменяет его. list=range(100)
, с другой стороны, вытирает исходное содержимое list
и устанавливает новое содержимое.
Но попробуйте следующее:
a=[1,2,3,4]
a[0:2]=[5,6]
a # prints [5,6,3,4]
Вы видите, мы изменили первые два элемента с назначением. Это означает, что с помощью этой нотации вы можете изменить несколько элементов в списке один раз.
Ответ 4
list[:]
будет работать только в том случае, если уже существует объект с именем list
, который позволяет назначать срез.
Кроме того, вы не должны указывать переменные list
, потому что есть встроенный именованный list
, который является самим типом list
.
Ответ 5
[:] также полезно сделать глубокую копию списка.
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
list [:] = range (100) обновляет список
list = range (100) создает новый список.
@agf: спасибо за указание моей ошибки
Ответ 6
list[:] = range(100)
не будет работать с неинициализированной переменной, так как он ее модифицирует. [:]
указывает весь список/touple.