2009-11-10 13 views

Odpowiedz

178

Istnieje silna kultura krotek dla heterogenicznych kolekcji, podobna do tej, która byłaby użyta w C, a listy są przeznaczone do jednorodnych kolekcji, podobnie jak w przypadku macierzy. Ale nigdy nie doszłam do tego z problemem zmienności wymienionym w innych odpowiedziach. Mutowalność ma do tego zęby (w rzeczywistości nie można zmienić krotki), podczas gdy homogeniczność nie jest egzekwowana, a więc wydaje się być znacznie mniej interesującym rozróżnieniem.

+3

@Ned, więc chciałbyś zaimplementować klasę punktów. Czy użyjesz krotki lub listy do przechowywania współrzędnych x, y, z? Chciałbyś zmienić wartości (idź z listą), ale jednocześnie kolejność i pozycja są znaczące i spójne (idź z krotką?). – Arlen

+18

Brakuje ci semantyki tego, porównując do niewłaściwej funkcji 'struct'. Krotki są przydatne, gdy _position ma relevance_ - najlepszy przykład pochodzi od współrzędnych w matematyce, która używa nawet tej samej składni: '(x, y, z)' – Izkata

+2

Nigdy wcześniej o tym nie słyszałem, ani nie zauważyłem tego jako wzorca w kodzie (i czytałem dużo kodu Pythona). –

75

wierzę (i jestem mało obeznany w Pythonie), że główną różnicą jest to, że krotka jest niezmienne (nie może być zmieniony w miejscu po cesji) i lista jest zmienny (ty można dodawać, zmieniać, odejmować itp.).

Tak więc, staram się tworzyć krotki, które nie powinny się zmieniać po przypisaniu, a moje listy mogą to zrobić.

+3

Dlaczego nie użyć listy, nawet jeśli nie planujesz mutacji? – KalEl

+2

@ KalEl Kilka innych odpowiedzi na tym wpisie wyjaśnia, dlaczego ktoś może użyć krotki na liście. – thornomad

484

Tuples mają ustalony rozmiar w naturze, natomiast lists są dynamiczne.
Innymi słowy, tuple jest niezmienny, podczas gdy jest zmienny.

  1. Nie można dodawać elementów do krotki. Krotki nie mają metody dodawania ani rozszerzania.
  2. Nie można usunąć elementów z krotki. Krotki nie mają metody usuwania ani pop.
  3. Elementy można znaleźć w krotce, ponieważ nie zmienia to krotki. Można również użyć operatora in, aby sprawdzić, czy element istnieje w krotce.

  • Krotki są szybsze niż list. Jeśli definiując stały zestaw wartości, a wszystko, co zamierzasz zrobić z tym, to iteruj za jego pomocą, użyj krotki zamiast listy.

  • Sprawia, że ​​twój kod jest bezpieczniejszy, jeśli "zapiszesz" dane, które nie wymagają zmiany. Używanie krotki zamiast listy jest jak posiadanie domniemanej twierdzącej twierdzącej, że dane te są stałe i że specjalna myśl (i określona funkcja) jest wymagana, aby to zmienić.

  • Niektóre krotki mogą być używane jako klucze słownika (w szczególności krotki zawierające niezmienne wartości, takie jak łańcuchy, liczby i inne krotki). Listy nigdy nie mogą być używane jako klucze słownika, ponieważ listy nie są niezmienne.

Źródło: Dive into Python 3

+23

Analogia "ochrony przed zapisem" idzie tak daleko: członkostwo krotki nie może być zmienione *, ale * zmienne elementy krotki * można * zmienić: l = lista(); t = (l, l); l.append (1) –

+2

Co sprawia, że ​​krotki są szybsze niż listy? –

+1

Krotki nie są szybsze niż lista. W [220] t_range = krotki (zakres (100000)) w [221]: 99999 w t_range Z [221] prawda w [222] l_range = Range (100000) w [223] : 99999 w l_range z [223] prawda w [224]: %% timeit .....: 99999 w l_range .....: 100 pętle, najlepiej od 3: 2,97 MS na pętlę w [225]: %% timeit .....: 99999 w t_range .....: 100 pętle, najlepiej od 3: 3,01 ms na pętli – Kracekumar

31

Musi być zmienny? Użyj listy. Czy nie może być zmienna? Użyj krotki.

W przeciwnym razie jest to kwestia wyboru.

W przypadku zbiorów heterogenicznych obiektów (takich jak adres podzielony na nazwisko, ulica, miasto, województwo i zamek) wolę używać krotki. Zawsze można je łatwo awansować na named tuples.

Podobnie, jeśli kolekcja ma być powtórzona, wolę listę. Jeśli jest to tylko pojemnik do przechowywania wielu obiektów jako jedno, wolę krotkę.

+2

To jest jedyna dobra odpowiedź tutaj. Podaje prawdę, a nie tylko zmienne/niezmienne rzeczy, które każdy zna. –

+3

Dlaczego używałbyś krotki, a nawet nazwanej krotki zamiast dyktatu? – GreenAsJade

+2

Pewne uzasadnienie preferencji byłoby miłe. Dlaczego preferujesz krotki dla heterogenicznych obiektów? Dlaczego wolisz listę, jeśli chcesz ją powtórzyć? – bugmenot123

10

Pierwszą rzeczą, którą należy zdecydować, jest to, czy struktura danych musi być zmienna czy nie. Jak już wspomniano, listy są zmienne, krotki nie. Oznacza to również, że do kluczy słownika można używać krotek, a listy uczestników nie.

Z mojego doświadczenia wynika, że ​​krotki są zwykle używane tam, gdzie porządek i pozycja są znaczące i spójne. Na przykład, tworząc strukturę danych do wyboru własnej gry przygodowej, zdecydowałem się użyć krotek zamiast list, ponieważ pozycja w kodzie była znacząca. Oto jeden z przykładów z tej struktury danych:

pages = {'foyer': {'text' : "some text", 
      'choices' : [('open the door', 'rainbow'), 
        ('go left into the kitchen', 'bottomless pit'), 
        ('stay put','foyer2')]},} 

Pierwsza pozycja w krotce jest wybór wyświetlane użytkownikowi, gdy grają w grę i drugie miejsce jest kluczem strony, że wybór idzie i to jest spójny dla wszystkich stron.

Krotki są również bardziej wydajne pod względem pamięci niż listy, chociaż nie jestem pewien, kiedy ta korzyść stanie się widoczna.

Zobacz także rozdziały na listach i krotkach w pozycji Think Python.

+0

Co sprawia, że ​​krotki są bardziej wydajne pod względem pamięci niż listy? –

+0

+1 - podczas gdy zmienność/niezmienność jest ważnym czynnikiem, pozycja mająca znaczenie jest głównym powodem - matematyka używa nawet tej samej składni dla układów współrzędnych: '(x, y, z)' – Izkata

+0

Dlaczego nie używasz dyktatur zamiast krotki, które mają nazwane wpisy? Nie jest dla mnie jasne, dlaczego stanowisko jest istotne w twoim przypadku: jedna to działanie, drugie to wynik ... jak powinienem (czytelnik) wiedzieć z góry, że to kolejność tych rzeczy? W twoim przypadku jest to dyskusyjne, ale widzę, że szersze krotki często używane, gdzie dostęp do nich staje się 'next_thing = result_tuple [5]'. 5? Naprawdę? Dlaczego 5? Czy nie byłoby lepiej powiedzieć "next_thing = result ['next_item']"? – GreenAsJade

8

Ale jeśli to ja zaprojektowałem API i wybieram typy danych, jakie są wytyczne?

Dla parametrów wejściowych najlepiej jest zaakceptować najbardziej ogólny interfejs, który spełnia to, czego potrzebujesz. Rzadko jest to tylko krotka lub lista - częściej jest to sekwencja, którą można kroić, a nawet iterować. Pisanie w języku Python zwykle odbywa się za darmo, chyba że wyraźnie zaznaczysz typy danych wejściowych. Nie rób tego, chyba że jest to absolutnie nieuniknione.

Dla danych, które produkujesz (parametry wyjściowe), po prostu zwróć najbardziej dogodny dla Ciebie wynik, np. zwróć dowolny typ danych, jaki zachowasz lub jakąkolwiek funkcję zwracaną przez helpera.

Należy pamiętać o unikaniu zwracania listy (lub innej zmiennej), która jest częścią twojego stanu, np.

class ThingsKeeper 
    def __init__(self): 
     self.__things = [] 

    def things(self): 
     return self.__things #outside objects can now modify your state 

    def safer(self): 
     return self.__things[:] #it's copy-on-write, shouldn't hurt performance 
+0

Więc jeśli masz funkcję i ma ona domyślny parametr dreaded metody (powiedzmy, listę), a zwrócisz ten parametr, kod na zewnątrz może teraz zadzierać z listą? –

+0

@RobertGrant Prawidłowo! Jeszcze jeden powód, aby użyć wzorca "Brak jako domyślny z wzorem" prolog ". Może być bardziej gadatliwy, ale unika nieprzyjemnych niespodzianek, takich jak ten. –

+0

Tak, to ma sens (i chciałbym powiedzieć, że myślę, że eliminuje to potrzebę domyślnych parametrów, aby zachowywać się tak, jak oni to robią, ale potem jestem krzykany na :)). Dzięki. –

1

Drobna, ale godna uwagi przewaga listy nad krotką polega na tym, że listy są nieco bardziej przenośne. Standardowe narzędzia rzadziej obsługują krotki. Na przykład JSON nie ma typu krotki. YAML ma, ale jego składnia jest brzydka w porównaniu do składni listy, co jest całkiem miłe.

W takich przypadkach możesz chcieć użyć wewnętrznie krotki, a następnie przekonwertować ją na listę w ramach procesu eksportowania. Alternatywnie, możesz chcieć używać list wszędzie dla spójności.

+2

Standardowy koder json konwertuje krotki na tablice. –

+0

Dzięki za wskazanie tego. Mój komentarz miał jednak ogólny sens. Osobiście eksportuję do yaml równie często jak json, aw takich przypadkach musiałbym ręcznie konwertować krotki na listy. –

Powiązane problemy