Próbowałem użyć wielokrotnego przypisania, jak pokazano poniżej, do zainicjowania zmiennych, ale byłem zdezorientowany zachowaniem, spodziewam się ponownego przypisania listy wartości oddzielnie, mam na myśli, że b [0] ic [0] równe 0, jak poprzednio.
a=b=c=[0,3,5]
a[0]=1
print(a)
print(b)
print(c)
Wynik to: [1, 3, 5] [1, 3, 5] [1, 3, 5]
Czy to jest poprawne? czego należy używać do wielokrotnego przypisania? co się od tego różni?
d=e=f=3
e=4
print('f:',f)
print('e:',e)
wynik: ('f:', 3) ('e:', 4)
a
,b
ic,
aby wszystko wskazuje na tę samą wartość (w tym przypadku lista), czy chcesza=0
,b=3
ic=5
. W takim razie chcesza,b,c = [0,3,5]
lub po prostua,b,c = 0,3,5
.Odpowiedzi:
Jeśli przychodzisz do Pythona z języka w C / Java / etc. rodzina, może pomóc ci przestać myśleć o niej
a
jako o „zmiennej” i zacząć o niej myśleć jak o „imieniu”.a
,b
ic
nie są różnymi zmiennymi o równych wartościach; są to różne nazwy tej samej identycznej wartości. Zmienne mają typy, tożsamości, adresy i wszelkiego rodzaju tego typu rzeczy.Nazwy tego nie mają. Wartości oczywiście mają i możesz mieć wiele nazw dla tej samej wartości.
Jeśli dajesz
Notorious B.I.G.
hot doga *Biggie Smalls
iChris Wallace
masz hot doga. Jeśli zmienisz pierwszy elementa
na 1, pierwsze elementyb
ic
będą miały wartość 1.Jeśli chcesz wiedzieć, czy dwie nazwy nazywają ten sam obiekt, użyj
is
operatora:>>> a=b=c=[0,3,5] >>> a is b True
Następnie pytasz:
d=e=f=3 e=4 print('f:',f) print('e:',e)
Tutaj ponownie wiążesz nazwę
e
z wartością4
. To nie ma wpływu na nazwyd
if
w żaden sposób.W poprzedniej wersji przypisywałeś do
a[0]
, a nie doa
. Więc z punktu widzeniaa[0]
, ponownie wiążesza[0]
, ale z punktu widzeniaa
zmieniasz to na miejscu.Możesz użyć
id
funkcji, która daje ci unikalny numer reprezentujący tożsamość obiektu, aby zobaczyć dokładnie, który obiekt jest którym, nawet jeśliis
nie możesz pomóc:>>> 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
Zauważ, że
a[0]
zmieniło się z 4297261120 na 4297261216 - jest to teraz nazwa innej wartości. Ab[0]
teraz jest to również nazwa tej samej nowej wartości. To dlatego, żea
ib
nadal nazywania tego samego obiektu.Pod okładkami
a[0]=1
faktycznie wywołuje metodę z obiektu listy. (Jest to równoważnea.__setitem__(0, 1)
.) Więc tak naprawdę nie jest to wcale ponowne wiązanie. To jak dzwonieniemy_object.set_something(1)
. Oczywiście, prawdopodobnie obiekt ponownie wiąże atrybut instancji w celu zaimplementowania tej metody, ale nie to jest ważne; ważne jest to, że niczego nie przypisujesz, po prostu mutujesz obiekt. To samo dotyczya[0]=1
.user570826 zadał pytanie:
To dokładnie ta sama sytuacja, co
a = b = c = [1, 2, 3]
: masz trzy nazwy dla tej samej wartości.Ale w tym przypadku wartość to an
int
, aint
s są niezmienne. W obu przypadkach możesza
ponownie przypisać inną wartość (np.a = "Now I'm a string!"
), Ale nie wpłynie to na oryginalną wartość, którab
ic
nadal będzie nazwami. Różnica polega na tym, że w przypadku listy możesz zmienić wartość[1, 2, 3]
na[1, 2, 3, 4]
, wykonując npa.append(4)
.; ponieważ to faktycznie zmienia wartość, którab
ic
są nazwami,b
teraz będzie b[1, 2, 3, 4]
. Nie ma sposobu, aby zmienić wartość10
na cokolwiek innego.10
ma 10 na zawsze, tak jak wampirzyca Claudia ma 5 na zawsze (przynajmniej do czasu zastąpienia jej przez Kirsten Dunst).* Ostrzeżenie: nie podawaj Notorious BIG hot doga. Zombie gangsta rapu nigdy nie powinny być karmione po północy.
źródło
have, a = b = c = 10;
i kiedy spróbujemy zaktualizować wartość b, wpłynie to na inne? chociaż sprawdziłem, że ich identyfikatory są takie same.?10
jest niezmienny - oznacza to, że nie ma możliwości zaktualizowania wartości, więc Twoje pytanie nie ma sensu. Możesz wskazaćb
inną wartość, ale nie ma to wpływu naa
ic
, które nadal wskazują oryginalną wartość. Różnica, jaką wprowadzają listy, polega na tym, że można je modyfikować - np. Możnaappend
przejść do listy lublst[0] = 3
, a to zaktualizuje wartość, która będzie widoczna we wszystkich nazwach tej wartości.Kaszel kaszel
>>> 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'} >>>
źródło
a,b,c = 1,2,3
bez nawiasów działa w Pythonie 2 lub 3, jeśli naprawdę potrzebujesz dodatkowego cm czytelności.Tak, to jest oczekiwane zachowanie. a, b i c są ustawione jako etykiety dla tej samej listy. Jeśli chcesz mieć trzy różne listy, musisz przypisać je indywidualnie. Możesz powtórzyć jawną listę lub użyć jednego z wielu sposobów kopiowania listy:
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
Instrukcje przypisania w Pythonie nie kopiują obiektów - wiążą nazwę z obiektem, a obiekt może mieć tyle etykiet, ile ustawisz. W swojej pierwszej edycji, zmieniając a [0], aktualizujesz jeden element pojedynczej listy, do której odnoszą się a, b i c. W drugim, zmieniając e, zmieniasz e, aby było etykietą dla innego obiektu (4 zamiast 3).
źródło
W Pythonie wszystko jest obiektem, także „proste” typy zmiennych (int, float itp.).
Kiedy zmieniasz wartość zmiennej, w rzeczywistości zmieniasz jej wskaźnik , a jeśli porównujesz dwie zmienne, porównuje ich wskaźniki . (Aby było jasne, wskaźnik to adres w fizycznej pamięci komputera, gdzie przechowywana jest zmienna).
W rezultacie, kiedy zmieniasz wartość zmiennej wewnętrznej, zmieniasz jej wartość w pamięci i wpływa to na wszystkie zmienne, które wskazują na ten adres.
Na przykład, kiedy:
a = b = 5
Oznacza to, że a i b wskazują na ten sam adres w pamięci, który zawiera wartość 5, ale kiedy to zrobisz:
a = 6
Nie ma to wpływu na b, ponieważ a jest teraz wskazuje na inną lokalizację pamięci, która zawiera 6, a b nadal wskazuje na adres pamięci zawierający 5.
Ale kiedy to zrobisz:
a = b = [1,2,3]
a i b ponownie wskazują na tę samą lokalizację, ale różnica polega na tym, że jeśli zmienisz jedną z wartości listy:
a[0] = 2
Zmienia wartość pamięci, na którą wskazuje a, ale a nadal wskazuje ten sam adres co b, w wyniku czego b również się zmienia.
źródło
PyObject
. Nie jest to prawdą w innych implementacjach, takich jak PyPy czy Jython. (W rzeczywistości nie jest nawet jasne, jak to może być prawdą, ponieważ języki, w których są napisane te implementacje, nie mają nawet wskaźników.)Możesz użyć,
id(name)
aby sprawdzić, czy dwie nazwy reprezentują ten sam obiekt:>>> a = b = c = [0, 3, 5] >>> print(id(a), id(b), id(c)) 46268488 46268488 46268488
Listy są zmienne; oznacza to, że możesz zmienić wartość bez tworzenia nowego obiektu. Zależy to jednak od tego, jak zmienisz wartość:
>>> 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]
Jeśli przypisać nową listę
a
, a następnie jego id ulegnie zmianie, więc nie wpłynie tob
ic
„s wartości:>>> 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]
Liczby całkowite są niezmienne, więc nie możesz zmienić wartości bez utworzenia nowego obiektu:
>>> 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
źródło
id
niekoniecznie jest miejscem pamięci. Jak mówią doktorzy , zwraca to „tożsamość… liczbę całkowitą… która gwarantuje unikalność i stałą dla tego obiektu podczas jego życia”. CPython używa adresu pamięci jako adresuid
, ale inne implementacje Pythona mogą tego nie robić. Na przykład PyPy nie. A powiedzenie „dwie zmienne wskazują na tę samą lokalizację pamięci” jest mylące dla każdego, kto je rozumie, w stylu C. „Dwie nazwy tego samego obiektu” jest zarówno bardziej dokładne, jak i mniej mylące.w swoim pierwszym przykładzie
a = b = c = [1, 2, 3]
naprawdę mówisz:'a' is the same as 'b', is the same as 'c' and they are all [1, 2, 3]
Jeśli chcesz ustawić „a” na 1, „b” na „2” i „c” na 3, spróbuj tego:
a, b, c = [1, 2, 3] print(a) --> 1 print(b) --> 2 print(c) --> 3
Mam nadzieję że to pomoże!
źródło
Mówiąc najprościej, w pierwszym przypadku przypisujesz wiele nazw do pliku
list
. W pamięci tworzona jest tylko jedna kopia listy, a wszystkie nazwy odnoszą się do tej lokalizacji. Zatem zmiana listy przy użyciu dowolnej nazwy faktycznie zmodyfikuje listę w pamięci.W drugim przypadku w pamięci tworzonych jest wiele kopii tej samej wartości. Zatem każda kopia jest od siebie niezależna.
źródło
Potrzebujesz tego:
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)
źródło
Kod, który robi to, czego potrzebuję, może wyglądać następująco:
# 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)
Wynik:
('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])
źródło