Una tupla è una raccolta immutabile di elementi in sequenza.
Come la maggior parte delle raccolte (vedi i tipi integrati list, dict e set), tuples può contenere qualsiasi tipo di dato (o più di uno), comprese altre tuples.
Gli elementi di una tupla si possono iterare con il costrutto for item in <tuple>.
Se servono sia l'indice sia il valore dell'elemento, si può usare for index, item in enumerate(<tuple>).
Come per qualsiasi sequenza, si può accedere agli elementi dentro tuples con la notazione a parentesi quadre, usando un 0-based index da sinistra o un -1-based index da destra.
Le tuple si possono copiare in tutto o in parte con la notazione slice o con <tuple>.copy(), e supportano tutte le operazioni comuni sulle sequenze.
Poiché sono immutabili, le tuples non supportano le operazioni sulle sequenze modificabili.
Le tuple occupano pochissimo spazio in memoria rispetto agli altri tipi di raccolta e hanno un tempo di accesso costante (O(1)) quando si usa un indice.
Tuttavia non si possono ridimensionare, ordinare o modificare dopo la creazione: sono quindi meno flessibili quando servono cambiamenti o aggiornamenti frequenti dei dati.
Se servono aggiornamenti o espansioni frequenti, una list, un collections.deque o un array.array potrebbero essere una struttura dati più adatta.
Le tuple si possono formare in diversi modi, usando il costruttore della classe tuple oppure la dichiarazione (<element_1>, <element_2>) (letterale tuple).
tuple() vuoto o con un iterabile:>>> no_elements = tuple()
()
# The constructor *requires* an iterable, so single elements must be passed in a list or another tuple.
>>> one_element = tuple([16])
(16,)
Le stringhe sono iterabili, quindi usare una singola str come argomento del costruttore tuple() può dare risultati sorprendenti:
# String elements (characters) are iterated through and added to the tuple
>>> multiple_elements_string = tuple("Timbuktu")
('T', 'i', 'm', 'b', 'u', 'k', 't', 'u')
Anche gli altri iterabili vedono i loro elementi aggiunti uno alla volta:
>>> multiple_elements_list = tuple(["Parrot", "Bird", 334782])
("Parrot", "Bird", 334782)
>>> multiple_elements_set = tuple({2, 3, 5, 7, 11})
(2,3,5,7,11)
L'iterazione predefinita di dict avviene sulle chiavi.
Per includere sia le chiavi sia i valori in una tupla creata da un dizionario, usa <dict>.items(),
che restituisce un iteratore di tuples (key, value).
>>> source_data = {"fish": "gold", "monkey": "brown"}
>>> multiple_elements_dict_1 = tuple(source_data)
('fish', 'monkey')
>>> multiple_elements_dict_2 = tuple(source_data.items())
(('fish', 'gold'), ('monkey', 'brown'))
Poiché il costruttore tuple() accetta come argomenti solo iterabili (o nulla), è molto più facile creare
una tupla con un solo elemento usando il metodo letterale.
>>> no_elements = ()
()
>>> one_element = ("Guava",)
("Guava",)
Tieni presente che in genere le parentesi non sono necessarie per creare un letterale tuple: bastano le virgole.
Tuttavia, usare (<element_1>, <element_2>) è considerato più leggibile nella maggior parte dei casi.
Le parentesi servono anche nei casi ambigui, come una tupla vuota o con un solo elemento, o quando una funzione accetta una tupla come argomento.
>>> elements_separated_with_commas = "Parrot", "Bird", 334782
("Parrot", "Bird", 334782)
>>> elements_with_commas_and_parentheses = ("Triangle", 60, 60, 60)
("Triangle", 60, 60, 60)
Altre strutture dati possono essere incluse come elementi di tuple, comprese altre tuples.
>>> nested_data_structures = ({"fish": "gold", "monkey": "brown", "parrot" : "grey"}, ("fish", "mammal", "bird"))
({"fish": "gold", "monkey": "brown", "parrot" : "grey"}, ("fish", "mammal", "bird"))
>>> nested_data_structures_1 = (["fish", "gold", "monkey", "brown", "parrot", "grey"], ("fish", "mammal", "bird"))
(["fish", "gold", "monkey", "brown", "parrot", "grey"], ("fish", "mammal", "bird"))
Le tuple si possono concatenare con l'operatore più +, che spacchetta ogni tuple e crea una nuova tupla combinata.
>>> new_via_concatenate = ("George", 5) + ("cat", "Tabby")
("George", 5, "cat", "Tabby")
#likewise, using the multiplication operator * is the equivalent of using + n times
>>> first_group = ("cat", "dog", "elephant")
>>> multiplied_group = first_group * 3
('cat', 'dog', 'elephant', 'cat', 'dog', 'elephant', 'cat', 'dog', 'elephant')
Si può accedere agli elementi dentro le tuple (come negli altri tipi sequenza str e list) con la notazione a parentesi quadre.
Gli indici possono andare da left --> right (a partire da zero) oppure da right --> left (a partire da -1).
Le tuple si possono anche copiare in tutto o in parte con la notazione slice o con <tuple>.copy().
>>> student_info = ("Alyssa", "grade 3", "female", 8)
#name is at index 0 or index -4
>>> student_name = student_info[0]
Alyssa
>>> student_name = student_info[-4]
Alyssa
#age is at index 3 or index -1
>>> student_age_1 = student_info[3]
8
>>> student_age_2 = student_info[-1]
8
Gli elementi dentro le tuple si possono iterare in un ciclo usando la sintassi for item in <tuple>.
Se servono sia gli indici sia i valori, si può usare for index, item in enumerate(<tuple>).
>>> student_info = ("Alyssa", "grade 3", "female", 8)
>>> for item in student_info:
... print(item)
...
Alyssa
grade 3
female
8
>>> for index, item in enumerate(student_info):
... print("Index is: " + str(index) + ", value is: " + str(item) + ".")
...
Index is: 0, value is: Alyssa.
Index is: 1, value is: grade 3.
Index is: 2, value is: female.
Index is: 3, value is: 8.
Le tuple sono spesso usate come record che contengono dati omogenei dal punto di vista organizzativo o concettuale e trattati come un'unica unità di informazione, anche se i singoli elementi sono di tipi di dato eterogenei.
>>> student_info = ("Alyssa", "grade 3", "female", 8)
Le tuple si usano anche quando servono sequenze immutabili e omogenee di dati per l'hashability, per la memorizzazione in un set o per la creazione di chiavi in un dizionario.
Tieni presente che, anche se le tuples nella maggior parte dei casi sono immutabili, poiché possono contenere qualsiasi struttura dati o oggetto possono diventare modificabili se uno dei loro elementi è di un tipo modificabile.
Usare un tipo di dato modificabile dentro una tuple rende la tuple che la contiene non hashable.
>>> cmyk_color_map = {
(.69, .3, .48, .1) : ("Teal 700", (59, 178, 146), 0x3BB292),
(0, .5, 1, 0) : ("Pantone 151", (247, 127, 1), 0xF77F01),
(.37, .89, 0, .44) : ("Pantone 267", (89, 16, 142), 0x59108E),
(0, 1, .46, .45) : ("Pantone 228", (140, 0, 76), 0x8C004C)
}
>>> unique_rgb_colors = {
(59, 178, 146),
(247, 127, 1),
(89, 16, 142),
(140, 0, 76),
(76, 0, 140)
}
>>> teal_700 = hash((59, 178, 146))
>>> teal_700 = hash(("Pantone 228", [(140, 0, 76), 0x8C004C]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Le tuple sono spesso usate come record, ma i dati al loro interno si possono accedere solo per posizione o indice.
La classe namedtuple() del modulo collections estende le funzionalità di base delle tuple per consentire l'accesso agli elementi per nome.
Inoltre, si può adattare una dataclass per ottenere una funzionalità simile di attributi con nome, con alcuni pro e contro.