{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Moduli e programma principale" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Talvolta un file Python può essere utilizzato sia come programma, lanciandolo direttamente, che come modulo da importare in altri programmi. È il caso, ad esempio, del file [hangman.py](https://fad.unich.it/pluginfile.php/319831/mod_page/content/10/hangman.py?time=1701099685331) della lezione di laboratorio del 27 novembre. Questo file contiene il programma dell'impiccato, ma viene anche importato dal file [test_hangman.py](https://fad.unich.it/pluginfile.php/319831/mod_page/content/10/test_hangman.py?time=1701101210726) che ne collauda le funzioni.\n", "\n", "È importante osservare che quando un modulo è importato, il programma pincipale contenuto al suo interno viene automaticamente eseguito, e se il programma fallisce con un errore l'importazione del modulo fallisce. Tuttavia, normalmente quando importiamo un modulo non vogliamo eseguire l'eventuale programma principale in esso contenuto: questo è sicuramente vero nel caso di test_hangman.py. Per far sì che il programma principale venga eseguito solo quando un file Python viene eseguito direttamente e non quando viene important, basta inserire il programma principale all'interno di questa istruzione if:\n", "```python\n", "if __name__ == \"__main__\":\n", " # qui va il programma principale\n", "```\n", "\n", "Quando un modulo Python viene importato, la variabile `__name__` (che è predefinita da Python, non dobbiamo crearla noi) viene inizializzata con il nome del modulo (normalmente il nome del file). Tuttavia, se il programma è stato eseguito direttamente e non a seguito di una importazione, allora la variabile `__name__` assume il valore speciale `__main__`. Pertanto, controllando questa variabile possiamo sapere se un file è in corso di esecuzione diretta o è stato importato come modulo." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Ancora sull'algoritmo di selection sort" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Riportiamo qui sotto la funzione che implementa l'algoritmo di ordinamento per selezione, e la funzione ausiliaria *minimum_position*." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "def minimum_position(l, start):\n", " \"\"\"\n", " Restituisce la posizione dell'elemento minimo nella sottolista l[start:].\n", " Si assume che start sia una posizione valida per l.\n", " \"\"\"\n", " minpos = start\n", " for i in range(start + 1, len(l)):\n", " if l[i] < l[minpos]:\n", " minpos = i\n", " return minpos\n", "\n", "def selection_sort(l):\n", " \"\"\"Ordina gli elementi di l.\"\"\"\n", " for i in range(len(l)-1):\n", " m = minimum_position(l, i)\n", " l[i], l[m] = l[m], l[i]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vogliamo provare il funzionamento di questo algoritmo e cerca di studiare quanto tempo richiede la sua esecuzione. Mentre per la ricerca lineare e la ricerca binaria abbiamo usato una lista di parole predefinita, per l'ordinamento preferiamo utilizzare liste di numeri generati artificialmente in maniera casuale." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "from random import randint\n", "\n", "def create_random_list(n):\n", " \"\"\"\n", " Restituisce una lista di lunghezza `n` riempita di numeri interi casuali tra\n", " zero e un milione.\n", " \"\"\"\n", " l = []\n", " # Quando una istruzione for viene usata per ripete delle istruzioni un\n", " # certo numero di volte e la variabile indice non è usata, è possibile\n", " # rimpiazzare la variabile indice con il simbolo di sottolineatura,\n", " # come fatto qui sotto.\n", " for _ in range(n):\n", " # Quando di scrive un numero, si possono usare i simboli di sottolineatura\n", " # per separare le cifre in gruppi di tre. La sottolineatura viene completamente\n", " # ignorata da Python, ma rende il numero più leggibile a un essere umano.\n", " l.append(randint(0, 1_000_000))\n", " return l" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[262309, 848062, 583484, 23601, 356783, 692346, 385810, 386928, 677911, 176078]" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "create_random_list(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vediamo quanto ci impiega *selection_sort* a ordinare una lista di 4000 elementi." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "l = create_random_list(4000)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "213 ms ± 1.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] } ], "source": [ "%%timeit\n", "selection_sort(l)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Il tempo di esecuzione di 213 ms è molto grande se confrontato con l'algoritmo di ricerca lineare (per non parlare di quella binaria). Nella lezione precedente, abbiamo visto che, sullo stesso computer, la ricerca lineare impiegava circa 13 ms nel caso peggiore a cercare un elemento in una lista enormemente più grande (400.000 elementi invece di 4000)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Proviamo adesso ad ordinare liste di lunghezza diversa, per vedere come il tempo di esecuzione dipende dalla lunghezza della lista." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Size 1000 Time: 0.014 secondi\n", "Size 2000 Time: 0.057 secondi\n", "Size 3000 Time: 0.118 secondi\n", "Size 4000 Time: 0.217 secondi\n", "Size 5000 Time: 0.334 secondi\n", "Size 6000 Time: 0.489 secondi\n", "Size 7000 Time: 0.650 secondi\n", "Size 8000 Time: 0.861 secondi\n", "Size 9000 Time: 1.087 secondi\n", "Size 10000 Time: 1.339 secondi\n", "Size 11000 Time: 1.618 secondi\n", "Size 12000 Time: 1.938 secondi\n", "Size 13000 Time: 2.281 secondi\n", "Size 14000 Time: 2.675 secondi\n", "Size 15000 Time: 3.023 secondi\n" ] } ], "source": [ "# importiamo la funzione time dal modulo time\n", "from time import time\n", "\n", "times = []\n", "for i in range(1000, 15001, 1000):\n", " l = create_random_list(i)\n", " # La funzione time restituisce il numero di secondi trascorsi dal 1° gennaio 1970.\n", " start_time = time()\n", " selection_sort(l)\n", " end_time = time()\n", " # La differenza tra end_time e start_time è la quantitià di tempo, in secondi, che è\n", " # stata impiegata dalla funzione selection_sort.\n", " times.append(end_time - start_time)\n", " print(f\"Size {i} Time: {end_time - start_time:10.3f} secondi\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si nota che quando la lunghezza della lista raddopia, il tempo di esecuzione aumenta di circa 4 volte. Ad esempio, per ordinare una lista di 5000 elementi ci sono voluti 0.334 secondi, mentre per ordinarne una di 10.000 ne sono stati necessari 1.339, e 1.339 / 0.334 è circa 4. Possiamo visualizzare l'andamento del tempo di esecuzione in funzione della lunghezza della lista col seguente codice (che non fa parte del programma del corso):" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from matplotlib import pyplot as plt\n", "plt.plot(range(1000,15001,1000),times)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Studio teorico\n", "\n", "Per uno studio teorico di come evolve il tempo di esecuzione dell'ordinamento per selezione al variare della lunghezza della lista in input, consultare la [lavagna della lezione del 28 novembre](https://fad.unich.it/mod/resource/view.php?id=27842) o la sezione 12.3 del libro di testo." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Tabelle e matrici" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Supponiamo di voler memorizzare una *tabella* come\n", "
\n",
    "2   3   4\n",
    "1   0  -3\n",
    "
\n", "in qualche modo dentro Python, e di voler fare la somma di tutti questi elementi. Useremo il termine *matrice* come sinonimo di *tabella*." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Possibili approcci" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Abbiamo varie possibilità:\n", "\n", "**1) usiamo una variabile diversa per ogni elemento della tabella**\n", "\n", "Questa soluzione è pessima, va bene solo se sappiamo a priori quanti elementi ha la tabella, ma se la tabella va letta da un file su memoria di massa o da Internet, e può avere dimensione variabile, non è assoluamente possibile seguire questo approccio. Ad ogni modo, il codice che mette tutti i dati della tabella di sopra nelle variabili opportune e le somma sarebbe il seguente:\n", "```python\n", "a = 2\n", "b = 3\n", "c = 4\n", "d = 1\n", "e = 0\n", "f = -3\n", "a * b * c * d * e * f\n", "```\n", "\n", "**2) usare una variabile diversa per ogni riga: ogni variabile è una lista degli elementi di quella riga**\n", "\n", "Un po' meglio di prima, ma non risolve veramente il problema, perché dobbiamo sapere a priori quante sono le righe della tabella (mentre siamo flessibili sulle colonne). L'esempio di sopra diventa:\n", "```python\n", "l1 = [2, 3, 4]\n", "l2 = [1, 0, -3]\n", "\n", "def sum_list(l):\n", " sum = 0\n", " for v in l:\n", " sum += v\n", " return sum\n", "\n", "sum_list(l1) + sum_list(l2)\n", "```\n", "\n", "Notare che il codice per eseguire il prodotto si è di molto complicato: abbiamo definito una funzione ausiliaria `sum_list` che esegue la somma di tutti gli elementi di una lista, e la richiamiamo per fare la somma degli elementi in `l1` ed in `l2`. Di contro, questa soluzione è indipendente dal numero di colonne: se le liste `l1` ed `l2` hanno 100 elementi invece di 3, il codice della somma funziona correttamente. Se invece aumenta il numero di righe, il codice della somma va modificato per prevedere la riga in più che è stata inserita.\n", "\n", "**3) usare una unica lista in cui inserire tutti gli elementi della tabella**\n", "\n", "Questa soluzione non è male, ed è indipendente sia dal numero di righe che dal numero di colonne della tabella.\n", "```python\n", "l = [ 2, 3, 4, 1, 0, -3 ]\n", "\n", "def sum_list(l):\n", " sum = 0\n", " for v in l:\n", " sum += v\n", " return sum\n", "\n", "sum_list(l)\n", "```\n", "\n", "Il problema di questa soluzione è che è un po' scomoda per il programmatore. Infatti non è immediato capire come accedere ad un elemento che sta in una certa riga e colonna: bisogna fare dei calcoli per determinare dove sta questo elemento. I calcoli in realtà non sono particolarmente difficili: l'elemento in riga `i` colonna `j` sta nella posizione `i * num_colonne + j` della lista `l`. Ad ogni modo, normalmente si preferisce adottare la soluzione che vedremo qui sotto.\n", "\n", "**4) utilizzare una unica lista di liste: gli elementi della lista sono le righe della tabella, ogni riga rappresentata essa stessa con una lista di numeri**\n", "\n", "L'idea è fondamentalmente partire dalla soluzione 2, ma impacchettare tutte le liste che contengono le righe della tabella in una unica lista di liste.\n", "```python\n", "l1 = [2, 3, 4]\n", "l2 = [1, 0, -3]\n", "l = [l1, l2]\n", "```\n", "o anche, più semplicemente\n", "```python\n", "l = [ [2,3,4], [1,0,-3]]\n", "```\n", "Per il programma che fa il prodotto dei numeri della tabella vediamo qui sotto.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Esperimenti" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[[2, 3, 4], [1, 0, -3]]" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Crea una lista formata da due elementi. Entrambi gli elementi sono a loro volta liste di numeri.\n", "l = [ [2, 3, 4], [1, 0, -3] ]\n", "l" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Gli elementi della lista `l` corrispondono alle righe della tabella." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[2, 3, 4]" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Il primo elemento è la lista [2, 3, 4], ovvero la prima riga della tabella\n", "l[0]" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 0, -3]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Il secondo elemento è la lista [2, 3, 4], ovvero la prima riga della tabella\n", "l[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Per accedere ad un singolo elemento della tabella bisogna prima selezionare la riga desiderata con un primo utilizzo dell'operatore di accesso alle liste (le parentesi quadre []), ed all'interno della riga selezionare la colonna desiderata con un secondo utilizzo dell'operatore di accesso alle liste. Ad esempio `l[0][1]` estrae la prima riga (perché `l[0] = [2, 3, 4]` è il primo elemento di `l`, quindi la prima riga) e poi su di esso applica l'operazione `[1]` che restituisce il secondo elemento di `[2, 3, 4]` ovvero il `3`. In sostanza, `l[0][1]` accede all'elemento di `l` in riga `0` e colonna `1` (come nel caso delle liste semplici, numero di riga e colonna iniziano da 0)." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l[0][1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Supponiamo ora di voler scrivere la funzione `somma_tabella` che somma tutti gli elementi di una tabella rappresentata utilizzando questa convenzione delle liste di liste. Un primo tentativo è il seguente, in cui passiamo esplicitamente alla funzione il numero di righe e colonne della tabella (vedremo poi che non sarà necessari)." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def somma_tabella(l, num_righe, num_colonne):\n", " \"\"\"\n", " Se l è una tabella con numero di righe e colonne specificato nei\n", " parametri, restituisce la somma di tutti i numeri in essa presenti.\n", " \"\"\"\n", " somma = 0\n", " # il primo for scorre tutte le righe\n", " for i in range(num_righe):\n", " # il secondo for scorre tutte le colonne\n", " for j in range(num_colonne):\n", " print(\"riga:\", i, \"colonna:\", j)\n", " somma += l[i][j]\n", " return somma" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "L'istruzione `print` dentro il codice è stata inserita per far vedere in che ordine vengono esaminate le celle della tabella, ed ovviamente andrebbe rimossa quando si intende utilizzare veramente la funzione." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "riga: 0 colonna: 0\n", "riga: 0 colonna: 1\n", "riga: 0 colonna: 2\n", "riga: 1 colonna: 0\n", "riga: 1 colonna: 1\n", "riga: 1 colonna: 2\n" ] }, { "data": { "text/plain": [ "7" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "somma_tabella(l, 2, 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Se si sbalia ad indicare il numero di righe o di colonne, `somma_tabella` può sommare solo una porzione della tabella, o dare errore qualora tenti di accedere a righe e colonne inesistenti." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "riga: 0 colonna: 0\n", "riga: 0 colonna: 1\n", "riga: 1 colonna: 0\n", "riga: 1 colonna: 1\n" ] }, { "data": { "text/plain": [ "6" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# somma solo le prime due colonne della tabella e ignora la terza\n", "somma_tabella(l, 2, 2)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "riga: 0 colonna: 0\n", "riga: 0 colonna: 1\n", "riga: 0 colonna: 2\n", "riga: 1 colonna: 0\n", "riga: 1 colonna: 1\n", "riga: 1 colonna: 2\n", "riga: 2 colonna: 0\n" ] }, { "ename": "IndexError", "evalue": "list index out of range", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/tmp/ipykernel_212888/3361396845.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# genera errore perché non esiste la terza riga\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0msomma_tabella\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ml\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m/tmp/ipykernel_212888/2981315666.py\u001b[0m in \u001b[0;36msomma_tabella\u001b[0;34m(l, num_righe, num_colonne)\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mj\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnum_colonne\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"riga:\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"colonna:\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mj\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m \u001b[0msomma\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0ml\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mj\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 13\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0msomma\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mIndexError\u001b[0m: list index out of range" ] } ], "source": [ "# genera errore perché non esiste la terza riga\n", "somma_tabella(l, 3, 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Rappresentazioni per righe o per colonne" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In tutti gli esempi visti fin'ora, abbiamo deciso di rappresentare le tabelle *per riga*: gli elementi di una riga stavano sempre insieme tra di loro. Ma sarebbe altrettanto ragionevole memorizzare la tabella *per colonne*. Riconsideriamo quindi la tabella dell'esempio di sopra, e vediamo come sarebbe utilizzare la rappresentazione per colonne.\n", "
\n",
    "2   3   4\n",
    "1   0  -3\n",
    "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**1) una variaìbile per ogni elemento**\n", "\n", "Non cambia nulla, questa rappresentazione non si può definire né per righe né per colonne\n", "\n", "**2) una variabile per ogni riga**\n", "\n", "Diventa **una variabile per ogni colonna**. Invece di\n", "```python\n", "l1 = [2, 3, 4]\n", "l2 = [1, 0, -3]\n", "```\n", "abbiamo\n", "```python\n", "c1 = [2, 1]\n", "c2 = [3, 0]\n", "c3 = [4, -3]\n", "```\n", "\n", "**3) una unica lista per tutti gli elementi**\n", "\n", "Cambia l'ordine degli elementi, non più una riga dopo l'altra ma una colonna dopo l'altra. Invece di\n", "```python\n", "l = [2, 3, 4, 1, 0, -3]\n", "```\n", "abbiamo\n", "```python\n", "l = [2, 1, 3, 0, 4, -3]\n", "```\n", "\n", "**4) lista di liste**\n", "\n", "Gli elementi della lista principale contengono le colonne della tabella. Invece di:\n", "```python\n", "l = [ [2,3,4], [1,0,-3] ]\n", "```\n", "abbiamo\n", "```python\n", "l = [ [2, 1], [3, 0], [4, -3] ]\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notare che l'interprete Python non sa niente di come decidete di memorizzare voi le tabelle: per lui si tratta solo di liste, cosa metterci dentro è compito del programmatore. Se scegliete di passare da una memorizzazione per righe ad una per colonne, dovrete sicuramente modificare buona parte del programma. Ad esempio, se utilizziamo il metodo 4 della lista di liste per memorizzare una tabella nella lista `l` adottando la appresentazione per righe e volete accedere all'elemento nella riga 0 colonna 1, l'espressione corretta è `l[0][1]`, ma se usate la rappresentazione per colonne dovete invece scrivere `l[1][0]`." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# rappresenta la solita tabella per righe ed estrae l'elemento nella riga 0 e colonna 1\n", "l_per_righe = [ [2, 3, 4], [1, 0, -3]]\n", "l[0][1]" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# rappresenta la solita tabella per colonne ed estrae l'elemento nella riga 0 e colonna 1\n", "l_per_colonne= [ [2,1], [3,0], [4,3] ]\n", "l_per_colonne[1][0]" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.0" } }, "nbformat": 4, "nbformat_minor": 2 }