В Python присваивание значений нескольким переменным с одинаковым значением? поведение списка



Я попытался использовать несколько назначений, как показано ниже, чтобы инициализировать переменные, но я запутался в поведении, я ожидаю переназначить список значений отдельно, я имею в виду b[0] и c[0] равный 0, как и раньше.



a=b=c=[0,3,5]
a[0]=1
print(a)
print(b)
print(c)


результат:
[1, 3, 5]
[1, 3, 5]
[1, 3, 5]



это правильно? что я должен использовать для этой операции?
чем отличается от этого?



d=e=f=3
e=4
print('f:',f)
print('e:',e)


результат:
('f:', 3)
('e:', 4)

1084   9  

9 ответов:

если вы переходите на Python с языка в C / Java / etc. семья, это может помочь вам перестать думать о a как "переменная", и начните думать о ней как о "имени".

a,b и c это не разные переменные с одинаковыми значениями; это разные имена для одного и того же одинакового значения. Переменные имеют типы, идентификаторы, адреса, и все подобные вещи.

имена не имеют ничего из этого. значения сделать, конечно, и вы можете иметь много имен для одного и того же значения.

если вы даете Notorious B.I.G. хот-дог,* Biggie Smalls и Chris Wallace горячий пес. Если вы измените первый элемент a к 1, первые элементы b и c в 1.

если вы хотите знать, если два имени называют один и тот же объект, используйте is оператор:

>>> a=b=c=[0,3,5]
>>> a is b
True

затем вы спросите:

чем отличается от это?

d=e=f=3
e=4
print('f:',f)
print('e:',e)

вот, ты перематываешь имя e стоимостью 4. Это не влияет на имена d и f в любом случае.

в предыдущей версии вы назначали a[0], а не a. Итак, с точки зрения a[0], ты перепривязки a[0], но с точки зрения a, вы меняете его на месте.

можно использовать id функция, которая дает вам некоторые уникальные число, представляющее идентичность объекта, чтобы точно видеть, какой объект является тем, что даже когда is могу помочь:

>>> a=b=c=[0,3,5]
>>> id(a)
4473392520
>>> id(b)
4473392520
>>> id(a[0])
4297261120
>>> id(b[0])
4297261120

>>> a[0] = 1
>>> id(a)
4473392520
>>> id(b)
4473392520
>>> id(a[0])
4297261216
>>> id(b[0])
4297261216

обратите внимание, что a[0] изменился с 4297261120 на 4297261216-теперь это имя для другого значения. И b[0] также теперь имя для того же самого нового значения. Это потому что a и b по-прежнему называя один и тот же объект.


под одеялом, a[0]=1 фактически вызывает метод в объекте списка. (Это эквивалентно a.__setitem__(0, 1).) Значит, это не действительно rebinding что-нибудь вообще. Это как позвонить my_object.set_something(1). Конечно, вероятно, что объект повторно связывает атрибут экземпляра для реализации этого метода, но это не важно; важно то, что вы ничего не назначаете, вы просто мутируете объект. И то же самое с a[0]=1.


user570826 спросил:

что делать если у нас, a = b = c = 10

вот точно такая же ситуация как a = b = c = [1, 2, 3]: у вас есть три названия одного и того же значения.

но в этом случае значение int и ints являются неизменяемыми. В любом случае, вы можете повторно привязать a к другому значению (например,a = "Now I'm a string!"), но не влияет на исходное значение, которое b и c все равно будут имена. Разница в том, что со списком можно изменить значение [1, 2, 3] на [1, 2, 3, 4] на практике, например,, a.append(4); так как это на самом деле меняет значение b и c имена для, b теперь будет b [1, 2, 3, 4]. Нет никакого способа изменить значение 10 на что-нибудь еще. 10 это 10 навсегда, так же, как Клаудия вампир 5 навсегда (по крайней мере, пока она не будет заменена Кирстен Данст).


* Предупреждение: Не давайте пресловутому B. I. G. хот-дог. Гангста-рэп зомби никогда не следует кормить после полуночи.

кхе-кхе

>>> a,b,c = (1,2,3)
>>> a
1
>>> b
2
>>> c
3
>>> a,b,c = ({'test':'a'},{'test':'b'},{'test':'c'})
>>> a
{'test': 'a'}
>>> b
{'test': 'b'}
>>> c
{'test': 'c'}
>>> 

Да, это ожидаемое поведение. a, b и c устанавливаются как метки для одного и того же списка. Если вы хотите три разных списка, вам нужно назначить их по отдельности. Вы можете либо повторить явный список, либо использовать один из многочисленных способов копирования списка:

b = a[:] # this does a shallow copy, which is good enough for this case
import copy
c = copy.deepcopy(a) # this does a deep copy, which matters if the list contains mutable objects

операторы присваивания в Python не копируют объекты - они привязывают имя к объекту, и объект может иметь столько меток, сколько вы установили. При первом редактировании, изменяя[0], вы обновляете один элемент единый список, на который ссылаются a, b и c. Во втором случае, изменяя e, вы переключаете e, чтобы быть меткой для другого объекта (4 вместо 3).

в python все является объектом, а также" простыми " типами переменных (int, float и т. д..).

когда вы изменяете значение переменной, вы на самом деле изменяет его указатель, и если вы сравниваете между двумя переменными это сравнивает их указатели. (Чтобы быть ясным, указатель-это адрес в памяти физического компьютера, где хранится переменная).

в результате, когда вы изменяете значение внутренней переменной, вы изменяете его значение в памяти и это влияет на все переменные, которые указывают на этот адрес.

для вашего примера, если вы:

a = b =  5 

Это означает, что A и B указывает на тот же адрес в памяти, который содержит значение 5, но когда вы делаете:

a = 6

это не влияет на b, потому что a теперь указывает на другую ячейку памяти, содержащую 6, А b все еще указывает на адрес памяти, содержащий 5.

но, когда вы делаете:

a = b = [1,2,3]

a и b, опять же, указывает на том же месте, но разница в том, что если вы измените одно из значений списка:

a[0] = 2

это изменяет значение памяти, на которую указывает a, но a по-прежнему указывает на тот же адрес, что и b, и в результате B также изменяется.

можно использовать id(name) чтобы проверить, если два имени обозначают один и тот же объект:

>>> a = b = c = [0, 3, 5]
>>> print(id(a), id(b), id(c))
46268488 46268488 46268488

списки изменчивы; это означает, что вы можете изменить значение на месте без создания нового объекта. Однако, это зависит от того, как вы измените значение:

>>> a[0] = 1
>>> print(id(a), id(b), id(c))
46268488 46268488 46268488
>>> print(a, b, c)
[1, 3, 5] [1, 3, 5] [1, 3, 5]

если вы назначаете новый список a, то его идентификатор изменится, так что это не повлияет b и c's значения:

>>> a = [1, 8, 5]
>>> print(id(a), id(b), id(c))
139423880 46268488 46268488
>>> print(a, b, c)
[1, 8, 5] [1, 3, 5] [1, 3, 5]

целые числа являются неизменными, поэтому вы не можете изменить значение без создания нового объект:

>>> x = y = z = 1
>>> print(id(x), id(y), id(z))
507081216 507081216 507081216
>>> x = 2
>>> print(id(x), id(y), id(z))
507081248 507081216 507081216
>>> print(x, y, z)
2 1 1

в первом примере a = b = c = [1, 2, 3] вы реально говорите:

 'a' is the same as 'b', is the same as 'c' and they are all [1, 2, 3]

Если вы хотите установить 'a' равным 1, ' b 'равным' 2 ' и ' c ' равным 3, попробуйте следующее:

a, b, c = [1, 2, 3]

print(a)
--> 1
print(b)
--> 2
print(c)
--> 3

надеюсь, что это помогает!

что вам нужно, это:

a, b, c = [0,3,5] # Unpack the list, now a, b, and c are ints
a = 1             # `a` did equal 0, not [0,3,5]
print(a)
print(b)
print(c)

проще говоря, в первом случае вы назначаете несколько имен list. Только один экземпляр списка хранится в памяти и все имена относятся к этому месту. Таким образом, изменение списка с использованием любого из имен фактически изменит список в памяти.

во втором случае в памяти создается несколько копий одного и того же значения. Таким образом, каждая копия независима друг от друга.

спасибо всем за разъяснения.

код, который делает то, что мне нужно, может быть такой:

#test
aux=[[0 for n in range(3)] for i in range(4)]
print('aux:',aux)
#initialization
a,b,c,d=[[0 for n in range(3)] for i in range(4)]
#changing values
a[0]=1
d[2]=5
print('a:',a)
print('b:',b)
print('c:',c)
print('d:',d)

результат: ('aux:', [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]) ('a:', [1, 0, 0]) ('b:', [0, 0, 0]) ('c:', [0, 0, 0]) ('d:', [0, 0, 5])

в отношении

Comments

    Ничего не найдено.