Назначение списка с помощью [:]

Какая разница между

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.