Przeczytałem kilka samouczków dotyczących języka Python (na przykład Dive Into Python) i odniesienie do języka na Python.org - nie rozumiem, dlaczego język wymaga krotek.
Krotki nie mają metod w porównaniu z listą lub zbiorem, a jeśli muszę przekonwertować krotkę na zestaw lub listę, aby móc je sortować, jaki jest sens używania krotki w pierwszej kolejności?
Niezmienność?
Dlaczego kogoś obchodzi, czy zmienna żyje w innym miejscu w pamięci niż wtedy, gdy została pierwotnie przydzielona? Wydaje się, że cała ta niezmienność w Pythonie jest zbyt mocno podkreślana.
W C / C ++, jeśli przydzielę wskaźnik i wskażę jakąś prawidłową pamięć, nie obchodzi mnie, gdzie znajduje się adres, o ile nie jest pusty, zanim go użyję.
Ilekroć odwołuję się do tej zmiennej, nie muszę wiedzieć, czy wskaźnik nadal wskazuje oryginalny adres, czy nie. Po prostu sprawdzam, czy nie ma null i używam go (lub nie).
W Pythonie, kiedy przydzielam ciąg (lub krotkę), przypisuję go do x, a następnie modyfikuję ciąg, dlaczego obchodzi mnie, czy to oryginalny obiekt? Dopóki zmienna wskazuje na moje dane, to wszystko się liczy.
>>> x='hello'
>>> id(x)
1234567
>>> x='good bye'
>>> id(x)
5432167
x
nadal odwołuje się do danych, które chcę, dlaczego ktoś musi się przejmować, czy jego identyfikator jest taki sam czy inny?
Odpowiedzi:
niezmienne obiekty mogą pozwolić na znaczną optymalizację; przypuszczalnie jest to powód, dla którego ciągi znaków są również niezmienne w Javie, tworzone całkiem osobno, ale mniej więcej w tym samym czasie co Python, i prawie wszystko jest niezmienne w prawdziwie funkcjonalnych językach.
w szczególności w Pythonie tylko niezmienne mogą być hashowalne (a zatem elementy zestawów lub klucze w słownikach). Ponownie, pozwala to na optymalizację, ale znacznie więcej niż tylko „znaczne” (projektowanie przyzwoitych tablic mieszających przechowujących całkowicie zmienne obiekty jest koszmarem - albo bierzesz kopie wszystkiego zaraz po zaszyfrowaniu, albo koszmar sprawdzania, czy hash obiektu zmienił się od czasu, gdy ostatnio odwołałeś się do tego, że podnosi swoją brzydką głowę).
Przykład problemu z optymalizacją:
źródło
random
wywołania (spróbuj to zrobić, zobaczysz!), Więc nie jest zbyt znaczące. Spróbuj,python -mtimeit -s "x=23" "[x,x]"
a zobaczysz bardziej znaczące przyspieszenie 2-3 razy przy tworzeniu krotki w porównaniu z budowaniem listy.Żadna z powyższych odpowiedzi nie wskazuje na rzeczywisty problem krotek i list, których wielu nowych w Pythonie wydaje się nie w pełni rozumieć.
Krotki i listy służą różnym celom. Listy przechowują jednorodne dane. Możesz i powinieneś mieć taką listę:
Powodem, dla którego jest to prawidłowe użycie list, jest to, że są to wszystkie jednorodne typy danych, a konkretnie nazwiska osób. Ale weź listę taką jak ta:
Ta lista zawiera pełne imię i nazwisko osoby oraz jej wiek. To nie jest jeden rodzaj danych. Prawidłowym sposobem przechowywania tych informacji jest krotka lub obiekt. Powiedzmy, że mamy kilka:
Niezmienność i zmienność krotek i list nie jest główną różnicą. Lista to lista elementów tego samego rodzaju: plików, nazw, obiektów. Krotki to grupa różnych typów obiektów. Mają różne zastosowania i wiele list nadużyć koderów Pythona dotyczących krotek.
Proszę nie.
Edytować:
Myślę, że ten post na blogu wyjaśnia, dlaczego uważam to lepiej niż ja: http://news.e-scribe.com/397
źródło
W tym konkretnym przypadku prawdopodobnie nie ma sensu. To nie jest problem, ponieważ nie jest to jeden z przypadków, w których rozważasz użycie krotki.
Jak zauważyłeś, krotki są niezmienne. Powody posiadania niezmiennych typów dotyczą krotek:
Zwróć uwagę, że konkretna implementacja Pythona może nie wykorzystywać wszystkich powyższych funkcji.
Klucze słownika muszą być niezmienne, w przeciwnym razie zmiana właściwości obiektu-klucza może unieważnić niezmienniki podstawowej struktury danych. W ten sposób krotki mogą być potencjalnie używane jako klucze. Jest to konsekwencja stałej poprawności.
Zobacz także „ Wprowadzenie krotek ” z Dive Into Python .
źródło
==
jest wdrażany na poziomie platformy.(1,2,3) == (1,2,3)
. To bardziej kwestia stażu.Czasami lubimy używać obiektów jako kluczy słownika
Na ile to jest warte, ostatnio wzrosły krotki (2.6+)
index()
icount()
metodyźródło
Zawsze uważałem, że posiadanie dwóch całkowicie oddzielnych typów dla tej samej podstawowej struktury danych (tablic) jest niezręcznym projektem, ale nie stanowi prawdziwego problemu w praktyce. (Każdy język ma swoje brodawki, w tym Python, ale to nie jest ważne).
To są różne rzeczy. Zmienność nie jest związana z miejscem, w którym jest przechowywana w pamięci; oznacza to, że rzeczy, na które wskazuje, nie mogą się zmienić.
Obiekty Pythona nie mogą zmieniać lokalizacji po ich utworzeniu, są modyfikowalne lub nie. (Dokładniej, wartość id () nie może się zmienić - to samo w praktyce.) Wewnętrzna pamięć obiektów podlegających zmianom może się zmienić, ale to jest ukryty szczegół implementacji.
To nie jest modyfikacja („mutacja”) zmiennej; tworzy nową zmienną o tej samej nazwie i odrzuca starą. Porównaj z operacją mutacji:
Jak zauważyli inni, pozwala to na używanie tablic jako kluczy do słowników i innych struktur danych, które wymagają niezmienności.
Pamiętaj, że klucze do słowników nie muszą być całkowicie niezmienne. Tylko jego część używana jako klucz musi być niezmienna; w przypadku niektórych zastosowań jest to ważna różnica. Na przykład możesz mieć klasę reprezentującą użytkownika, która porównuje równość i skrót według unikalnej nazwy użytkownika. Możesz wtedy zawiesić inne zmienne dane w klasie - „użytkownik jest zalogowany” itp. Ponieważ nie ma to wpływu na równość ani na hash, jest możliwe i całkowicie poprawne użycie tego jako klucza w słowniku. Nie jest to zbyt często potrzebne w Pythonie; Zwracam na to uwagę, ponieważ kilka osób twierdziło, że klucze muszą być „niezmienne”, co jest tylko częściowo poprawne. Jednak używałem tego wiele razy z mapami i zestawami C ++.
źródło
Jak podał w komentarzu gnibbler, Guido miał opinię, która nie jest w pełni akceptowana / doceniana: „listy są dla danych jednorodnych, krotki są dla danych heterogenicznych”. Oczywiście wielu przeciwników zinterpretowało to w ten sposób, że wszystkie elementy listy powinny być tego samego typu.
Lubię to widzieć inaczej, podobnie jak inni też w przeszłości:
Zauważ, że uważam alist za jednorodny, nawet jeśli typ (alist [1])! = Typ (alist [2]).
Jeśli mogę zmienić kolejność elementów i nie będę miał problemów w swoim kodzie (poza założeniami np. „Należy posortować”) to należy skorzystać z listy. Jeśli nie (jak w krotce
blue
powyżej), powinienem użyć krotki.źródło
Są ważne, ponieważ gwarantują wywołującemu, że obiekt, który przekazują, nie zostanie zmutowany. Jeśli to zrobisz:
Dzwoniący nie ma gwarancji wartości a po wywołaniu. Jednak,
Teraz ty jako dzwoniący lub jako czytelnik tego kodu wiesz, że a jest tym samym. W tym scenariuszu zawsze możesz zrobić kopię listy i przekazać ją, ale teraz marnujesz cykle zamiast używać konstrukcji językowej, która ma większy sens semantyczny.
źródło
możesz zobaczyć tutaj dyskusję na ten temat
źródło
Twoje pytanie (i dalsze komentarze) skupiają się na tym, czy id () zmienia się podczas zadania. Skoncentrowanie się na tym następczym efekcie różnicy między niezmiennym zastępowaniem obiektu a modyfikacją obiektu zmiennego zamiast samej różnicy nie jest być może najlepszym podejściem.
Zanim przejdziemy dalej, upewnij się, że zachowanie przedstawione poniżej jest takie, jakiego oczekujesz od Pythona.
W tym przypadku zawartość a2 została zmieniona, mimo że tylko a1 miała przypisaną nową wartość. Porównaj z poniższym:
W tym drugim przypadku zastąpiliśmy całą listę, zamiast aktualizować jej zawartość. W przypadku niezmiennych typów, takich jak krotki, jest to jedyne dozwolone zachowanie.
Dlaczego to ma znaczenie? Powiedzmy, że masz dyktando:
Używając krotki, słownik jest bezpieczny przed zmienianiem kluczy „spod niego” na elementy, które mają inną wartość. Ma to kluczowe znaczenie dla skutecznego wdrożenia.
źródło