Próbuję zrozumieć, jak niezmienność działa w python. Ponieważ ciąg znaków jest niezmienny w pythonie, spodziewałem się, że id zmieni się za każdym razem, gdy wykonam operację łańcuchową, ale nie działa zgodnie z oczekiwaniami. przykład: Ostatnia operacja na t nie zmienia jej identyfikatora. Jakieś pomysły, dlaczego?Immutability in Python
Odpowiedz
miałem wiersz jabłek w różnych komórkach [memory containing variables (I will not go to the bit level)]
, z których niektóre są puste [cells containing garbage/empty value]
.
Wziąłem jedno. Było to w komórce 3 [logical address = 3]
.
Pomalowałem go na niebiesko (po sklonowaniu go za pomocą przyszłej techniki, w celu pokazania niezmienności) [committed an operation on it, same could go for addition for integers]
.
Spojrzałem, gdzie to umieścić, i chociaż komórka 4 była wolna, komórka 3 była również (ponieważ "oryginalne" jabłko już nie ma)! Więc umieściłem to z powrotem w komórce 3 [and although we get a "new" apple, it has the same address]
.
samo dotyczy t
(zauważ, że id
jest adres pamięci zmiennej w CPython), ale ponieważ mówimy o „łańcuchów jabłek” tutaj (struny wykonane są z sekwencji znaków, mamy aby wziąć pod uwagę ilość miejsca musimy kontynuować sekwencję, więc gdybym miała moja pamięć wygląda jak (_
trybuny dla dowolnych danych śmieci, „^” na przestrzeni)
H e l l o _ _ _ _ _ B O O M
^ string pointer points here
i chciałem zmienić ciąg "Hello you"
, Mogę rozważyć użycie wolnej przestrzeni:
H e l l o^y o u _ B O O M
^ string pointer points here
Ale jeśli chcę zmienić ciąg "Hello world!"
, musiałbym szukać wolnego miejsca w długości "Hello world!"
gdzieś indziej (może mamy ją tuż po "BOOM"
, co jest prawdopodobne w środowisku śmieci zbierane, zobacz, jak różnią się Twoje identyfikatory):
H e l l o^y o u _ B O O M _ H e l l o^w o r l d ! _ G A R B A G E
^string pointer points here
@ B.M. Problemem jest podobieństwo do interningu. To, co napisałem, jest zasadniczo podobne do komentarza Martijna - "" Python może ponownie wykorzystać gniazda pamięci. "' – Uriel
@ B.M.Nie rozumiem, co masz na myśli mówiąc "To nie działa [sic!]". Opis tej odpowiedzi polega na tym, że Python ponownie wykorzystuje adres pamięci dla nowego ciągu, ponieważ poprzedni ciąg znaków został zbuforowany. Spojrzałem na link i nie widzę, jak mogłoby to zapewnić alternatywne wyjaśnienie zjawiska opisanego w pytaniu. –
Przepraszam, to było zbyt bezpośrednie. Publikuję coś, co wyjaśni, co zrozumiałem. Myślę, że w tym przykładzie niebieskie jabłko nie jest umieszczane w komórce 3, po prostu wpuszczasz tutaj zieloną i dodajesz niebieską farbę na końcu komórki3. –
Identyfikatory obiektów można ponownie wykorzystać, o ile oryginalny obiekt nie jest już obecny. Nie jest to specyficzne dla łańcuchów, ale dla wszystkich typów Pythona. Na najprostszym przykładzie, można sprawdzić identyfikator prosty object
:
>>> print id(object())
140437485756544
>>> print id(object())
140437485756544
Jeśli jednak zachować odniesienie do poprzedniego obiektu, id nie zostaną ponownie wykorzystane:
>>> a = object()
>>> id(a)
140437485756544
>>> b = object()
>>> id(b)
140437485756560
Można odtworzyć to samo zachowanie w testach z ciągami, dołączając do listy wyniki pośrednie (wartości w t
).
Dlaczego w pierwszych dwóch przypadkach testowych dołączania "Test" do t zmienił się identyfikator? Czy jest to "losowe" czy python ma systematyczny sposób przydzielania pamięci dla ciągów znaków w tym przypadku? – PrestonM
@ PrestonM Nie można zagwarantować, że identyfikator zostanie ponownie użyty - coś innego mogło zająć tę lokalizację pamięci (w ten sposób CPython implementuje 'id') za pierwszym razem. Gwarantuje to, że ID obiektu aktywnego nie ulegnie zmianie i że dwa różne (i żywe) obiekty nie będą miały tego samego identyfikatora. – user4815162342
To ma sens. Dzięki! – PrestonM
Powiązane: [Informacje o zmianie identyfikatora niezmiennego łańcucha Pythona] (http://stackoverflow.com/questions/24245324/about-tanging-id-of-a-python-immutable-string) – fredtantini
Naprawdę nie znoszę, jak ta optymalizacja narusza semantykę języka Python. Zgodnie z semantyką języka wartości 't' przed i po' + = 'powinny być różnymi obiektami z (ledwo) nakładającymi się okresami życia, więc nie powinno im się dzielić' id'. – user2357112