Zrozumiałem, że ciągi znaków w Pythonie są niezmienne.
Wypróbowałem następujący kod:
a = "Dog"
b = "eats"
c = "treats"
print a, b, c
# Dog eats treats
print a + " " + b + " " + c
# Dog eats treats
print a
# Dog
a = a + " " + b + " " + c
print a
# Dog eats treats
# !!!
Czy Python nie powinien był uniemożliwić przypisania? Prawdopodobnie czegoś mi brakuje.
Dowolny pomysł?
python
string
immutability
mutability
Jason
źródło
źródło
id()
funkcję.a
będzie miał inny identyfikator przed i po przypisaniu, co oznacza, że wskazuje na różne obiekty. Podobnie w przypadku takiego kodu,b = a
który znajdziesza
ib
będzie miał ten sam identyfikator, wskazujący, że odwołują się do tego samego obiektu.Odpowiedzi:
Najpierw
a
wskazał na napis „Pies”. Następnie zmieniłeś zmienną,a
aby wskazywała na nowy ciąg znaków „Pies zjada smakołyki”. W rzeczywistości nie zmutowałeś ciągu „Pies”. Ciągi znaków są niezmienne, zmienne mogą wskazywać na cokolwiek chcą.źródło
Same obiekty string są niezmienne.
Zmienna
a
wskazująca na łańcuch jest modyfikowalna.Rozważać:
źródło
a.append(3)
to nie to samo coa = a + 3
. Nie jest równea += 3
(dodawanie w miejscu jest równoważne z.extend
, a nie z.append
).+
zachowuje się tak samo dla list i ciągów - łączy się, tworząc nową kopię i nie modyfikując żadnego operandu.append
funkcji, ponieważ są niezmienne.Zmienna a wskazuje na obiekt „Pies”. Najlepiej jest myśleć o zmiennej w Pythonie jako o tagu. Możesz przenieść znacznik do różnych obiektów, tak jak zrobiłeś to po zmianie
a = "dog"
naa = "dog eats treats"
.Jednak niezmienność odnosi się do przedmiotu, a nie do tagu.
Jeśli próbowałeś
a[1] = 'z'
dokonać"dog"
w"dzg"
dostaniemy błąd:ponieważ łańcuchy nie obsługują przypisywania pozycji, dlatego są niezmienne.
źródło
Coś jest zmienne tylko wtedy, gdy jesteśmy w stanie zmienić wartości przechowywane w lokalizacji pamięci bez zmiany samej lokalizacji pamięci.
Sztuczka polega na tym, że jeśli okaże się, że lokalizacja pamięci przed i po zmianie jest taka sama, jest zmienna.
Na przykład lista jest zmienna. W jaki sposób?
Ciąg jest niezmienny. Jak to udowodnimy?
dostajemy
Więc nie udało nam się zmutować łańcucha. Oznacza to, że ciąg jest niezmienny.
Podczas ponownego przypisywania zmieniasz zmienną, aby wskazywała na nową lokalizację. Tutaj nie zmutowałeś łańcucha, ale zmutowałeś samą zmienną. Oto, co robisz.
id
przed i po zmianie jest inny, więc to dowodzi, że tak naprawdę nie mutujesz, ale kierujesz zmienną do nowej lokalizacji. Co nie jest mutacją tego ciągu, ale mutacją tej zmiennej.źródło
Zmienna to po prostu etykieta wskazująca na obiekt. Obiekt jest niezmienny, ale jeśli chcesz, możesz ustawić etykietę na zupełnie inny obiekt.
źródło
Rozważać:
Zauważ, że szesnastkowa lokalizacja pamięci nie zmieniła się, gdy dwukrotnie zapisałem tę samą wartość w zmiennej. Zmieniło się, kiedy zapisałem inną wartość. Ciąg jest niezmienny. Nie z powodu gorliwości, ale dlatego, że płacisz karę za wydajność tworzenia nowego obiektu w pamięci. Zmienna
a
to tylko etykieta wskazująca na ten adres pamięci. Można go zmienić, aby wskazywał cokolwiek.źródło
Oświadczenie
a = a + " " + b + " " + c
można podzielić na podstawie wskazówek.a + " "
mówi, daj mia
punkty, których nie można zmienić, i dodaj" "
do mojego obecnego zestawu roboczego.pamięć:
+ b
mówi, daj mib
punkty, których nie można zmienić, i dodaj to do bieżącego zestawu roboczego.pamięć:
+ " " + c
mówi dodaj" "
do bieżącego zestawu. Następnie podaj mi, do jakichc
punktów nie można zmienić i dodaj to do bieżącego zestawu roboczego. pamięć:Na koniec
a =
mówi ustaw mój wskaźnik, aby wskazywał na wynikowy zestaw.pamięć:
"Dog"
jest odzyskiwany, ponieważ żadne więcej wskaźników nie łączy się z jego fragmentem pamięci. Nigdy nie modyfikowaliśmy sekcji pamięci,"Dog"
w której się znajdowała, co oznacza niezmienność. Możemy jednak zmienić, które etykiety, jeśli w ogóle, wskazują na tę sekcję pamięci.źródło
źródło
Istnieje różnica między danymi a etykietą, z którą są skojarzone. Na przykład, kiedy to robisz
dane
"dog"
są tworzone i umieszczane pod etykietąa
. Etykieta może się zmienić, ale to, co jest w pamięci, nie. Po wykonaniu tych czynności dane"dog"
nadal będą istnieć w pamięci (do momentu ich usunięcia przez moduł odśmiecania pamięci)W twoim programie
a
teraz ^ wskazuje na ^,"cat"
ale łańcuch"dog"
się nie zmienił.źródło
Ciągi Pythona są niezmienne. Jednak
a
nie jest ciągiem znaków: jest to zmienna o wartości ciągu. Nie możesz zmutować ciągu, ale możesz zmienić wartość zmiennej na nowy ciąg.źródło
Zmienne mogą wskazywać dowolne miejsce. Jeśli wykonasz te czynności, zostanie zgłoszony błąd:
źródło
Obiekty łańcuchowe w Pythonie są niezmienne. Przykład:
W tym przykładzie widzimy, że gdy przypisujemy inną wartość w a, to nie modyfikuje, powstaje nowy obiekt
I nie można go modyfikować. Przykład:
Wystąpił błąd.
źródło
„mutable” oznacza, że możemy zmienić zawartość ciągu, „immutable” oznacza, że nie możemy dodać dodatkowego ciągu.
źródło
>>> a = 'dogs'
>>> a.replace('dogs', 'dogs eat treats')
'dogs eat treats'
>>> print a
'dogs'
Niezmienne, prawda ?!
Część dotycząca zmiany zmiennej została już omówiona.
źródło
replace()
metoda zwraca nowy ciąg.Rozważ ten dodatek do swojego przykładu
Jedno z dokładniejszych wyjaśnień, które znalazłem na blogu, to:
Link do bloga: https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/
źródło
Dodanie nieco więcej do powyższych odpowiedzi.
id
zmiennej zmienia się po ponownym przypisaniu.Co oznacza, że zmieniliśmy zmienną,
a
aby wskazywała na nowy ciąg. Teraz istnieją dwastring
(str) obiekty:'initial_string'
gdzieid
= 139982120425648i
'new_string'
gdzieid
= 139982120425776Rozważ poniższy kod:
Teraz
b
wskazuje na'initial_string'
i ma to samo,id
coa
przed ponownym przypisaniem.Zatem
'intial_string'
nie został zmutowany.źródło
Zreasumowanie:
Niezmienne:
Niezmienny:
To jest błąd w Pythonie 3, ponieważ jest niezmienny. I nie jest to błąd w Pythonie 2, ponieważ oczywiście nie jest niezmienny.
źródło
Funkcja wbudowana
id()
zwraca tożsamość obiektu jako liczbę całkowitą. Ta liczba całkowita zwykle odpowiada położeniu obiektu w pamięci.Początkowo „a” jest przechowywane w lokalizacji pamięci 139831803293008, ponieważ obiekt ciągu znaków jest niezmienny w Pythonie, jeśli spróbujesz zmodyfikować i ponownie przypisać odniesienie zostanie usunięte i będzie wskaźnikiem do nowej lokalizacji pamięci (139831803293120).
źródło
źródło
Ten obraz daje odpowiedź. Proszę przeczytaj to.
źródło
Po prostu łączymy dwie wartości łańcuchowe. Nigdy nie zmieniamy wartości (a). Przed chwilą (a) reprezentują kolejny blok pamięci, który ma wartość „dogdog”. Ponieważ w zapleczu jedna zmienna nigdy nie reprezentuje dwóch bloków pamięci w tym samym czasie. Wartość (a) przed konkatenacją to „pies”. Ale potem (a) reprezentują "psa", ponieważ teraz (a) w zapleczu rep. blok, który ma wartość „dogdog”. A „pies” to przedstawiciel. by (b) i „pies” nie jest liczone jako wartość śmieci, dopóki (b) nie reprezentuje „psa”.
Nieporozumienie polega na tym, że reprezentujemy bloki pamięci (które zawierają dane lub informacje) w zapleczu o tej samej nazwie zmiennej.
źródło
Możesz uczynić tablicę numpy niezmienną i użyć pierwszego elementu:
następnie:
lub
źródło