Track
/
Python
Python
/
Esercizi
/
Le fantastiche lasagne di Guido
Le fantastiche lasagne di Guido

Le fantastiche lasagne di Guido

Esercizio di apprendimento

Introduzione

Python è un linguaggio di programmazione tipizzato dinamicamente e fortemente. Utilizza sia il duck typing sia la tipizzazione graduale tramite i type hints.

Sebbene Python supporti molti stili di programmazione diversi, internamente in Python tutto è un oggetto. Questo vale per i numeri, le stringhe, gli array e persino le funzioni.

Scopriremo meglio cosa significa tutto questo mentre proseguiamo nel percorso.

Questo primo esercizio introduce 4 funzionalità principali del linguaggio Python:

  1. Assegnazione di nomi (variabili e costanti),
  2. Funzioni (la parola chiave def e la parola chiave return),
  3. Commenti, e
  4. Docstring.

Note

In generale, i contenuti, i test e gli strumenti di analisi del percorso Python seguono le convenzioni di stile descritte in PEP 8 e PEP 257 per lo stile del codice Python, con l'ulteriore (forte) suggerimento di non usare nomi di variabili composti da una sola lettera o variabili chiamate "_".

Nel percorso Python, le variabili sono sempre scritte in snake_case e le costanti in SCREAMING_SNAKE_CASE.


Assegnazione di nomi (variabili e costanti)

Chi programma può associare dei nomi (detti anche variabili) a qualsiasi tipo di oggetto usando l'operatore di assegnazione =: <name> = <value>. Un nome può essere riassegnato (o riassociato) a valori diversi (e a oggetti di tipo diverso) nel corso della sua esistenza.

>>> my_first_variable = 1  #<-- my_first_variable bound to an integer object of value one.
>>> my_first_variable = 2  #<-- my_first_variable re-assigned to integer value 2.

>>> print(type(my_first_variable))
<class 'int'>

>>> print(my_first_variable)
2

>>> my_first_variable = "Now, I'm a string." #<-- You may re-bind a name to a different object type and value.
>>> print(type(my_first_variable))
<class 'str'>

>>> my_first_variable = 'You can call me "str".' #<-- Strings can be declared using single or double quote marks.
>>> print(my_first_variable)
You can call me "str".

Costanti

Le costanti sono nomi pensati per essere assegnati una sola volta in un programma. Dovrebbero essere definite a livello di modulo (file) e sono in genere visibili a tutte le funzioni e le classi del programma. Usare SCREAMING_SNAKE_CASE segnala che il nome non dovrebbe essere riassegnato, né dovrebbe essere modificato il suo valore.

Funzioni

La parola chiave def dà inizio a una definizione di funzione. Ogni funzione può avere zero o più parametri formali tra parentesi (), seguiti da due punti :. Le istruzioni che formano il corpo della funzione iniziano sulla riga successiva a def e devono essere indentate in un blocco.

# The body of a function is indented by 2 spaces, & prints the sum of the numbers.
def add_two_numbers(number_one, number_two):
  total = number_one + number_two
  print(total)  

>>> add_two_numbers(3, 4)
7


# Inconsistent indentation in your code blocks will raise an error.
>>> def add_three_numbers_misformatted(number_one, number_two, number_three):
...     result = number_one + number_two + number_three   # This was indented by 4 spaces.
...    print(result)     #this was only indented by 3 spaces
...
...
  File "<stdin>", line 3
    print(result)
    ^
IndentationError: unindent does not match any outer indentation level

Le funzioni restituiscono esplicitamente un valore o un oggetto tramite la parola chiave return:

# Function definition on first line, explicit return used on final line.
>>> def add_two_numbers(number_one, number_two):
        return number_one + number_two   


# Calling the function in the Python shell returns the sum of the numbers.
>>> add_two_numbers(3, 4)
7

# Assigning the function call to a variable and printing it 
# will also return the value.
>>> sum_with_return = add_two_numbers(5, 6)
>>> print(sum_with_return)
11

Le funzioni che non hanno un'espressione esplicita dopo un return restituiranno implicitamente l'oggetto None. I dettagli di None saranno trattati in un esercizio successivo. Ai fini di questo esercizio e di questa spiegazione, None è un segnaposto che rappresenta nulla, o null:


# This function will return `None`
def square_a_number(number):
    square = number * number
    return # <-- note that this return is not followed by an expression

# Calling the function in the Python shell appears 
# to not return anything at all.
>>> square_a_number(2)
>>>


# Using print() with the function call shows that 
# the function is actually returning the **None** object.
>>> print(square_a_number(2))
None

Anche le funzioni che omettono return restituiranno implicitamente l'oggetto None. Questo significa che se non usi return in una funzione, Python restituirà l'oggetto None al posto tuo.

# This function omits a return keyword altogether.
def add_two_numbers(number_one, number_two):
  result = number_one + number_two

>>> add_two_numbers(5, 7)
>>> print(add_two_numbers(5, 7))
None

# Assigning the function call to a variable and printing 
# the variable will also show None.
>>> sum_without_return = add_two_numbers(5, 6)
>>> print(sum_without_return)
None

Chiamare le funzioni

Le funzioni sono chiamate usando il loro nome seguito da (). La notazione con il punto (.) si usa per chiamare funzioni definite all'interno di una classe o di un modulo.

>>> def raise_to_power(number, power):
...     return number ** power
...

>>> raise_to_power(3,3) # <--Invoking the function with the arguments 3 and 3.
27


# A mismatch between the number of parameters and the number of arguments will raise an error.
>>> raise_to_power(4,)
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: raise_to_power() missing 1 required positional argument: 'power'


# Calling methods or functions in classes and modules.
>>> start_text = "my silly sentence for examples."
>>> str.upper(start_text)  # <--Calling the upper() method from the built-in str class on start_text.
'MY SILLY SENTENCE FOR EXAMPLES.'


# Importing the math module
>>> import math

>>> math.pow(2,4)  # <--Calling the pow() function from the math module.
16.0

Commenti

I commenti in Python iniziano con un # che non fa parte di una stringa e terminano a fine riga. A differenza di molti altri linguaggi di programmazione, Python non supporta i marcatori di commento su più righe. Ogni riga di un blocco di commento deve iniziare con il carattere #.

Docstring

La prima istruzione del corpo di una funzione può essere, facoltativamente, una docstring, che riassume in breve lo scopo della funzione o dell'oggetto. Le docstring si dichiarano con tre virgolette doppie (""") indentate allo stesso livello del blocco di codice:


# An example from PEP257 of a multi-line docstring
# reformatted to use Google style non-type hinted docstrings.
# Some additional details can be found in the Sphinx documentation:
# https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html#getting-started

def complex(real=0.0, imag=0.0):
    """Form a complex number.

    Keyword Arguments:
        real (float): The real part of the number (default 0.0)
        imag (float): The imaginary part of the number (default 0.0)
        
    """

    if imag == 0.0 and real == 0.0:
        return complex_zero

Le docstring vengono lette da strumenti di documentazione automatica come Sphinx e sono restituite chiamando l'attributo speciale .__doc__ sulla funzione, sul metodo o sulla classe. Le convenzioni generali per le docstring sono descritte in PEP257, ma i formati esatti variano da progetto a progetto e da team a team. Gli esercizi sui concetti di Exercism cercano di seguire lo stile Google per il codice senza type hints.

Le docstring possono anche funzionare come test di unità leggeri, che saranno trattati in un esercizio successivo.

# An example on a user-defined function using a Google style docstring. 
>>> def raise_to_power(number, power):
    """Raise a number to an arbitrary power.

    Parameters:
        number (int): The base number.
        power (int): The power to raise the base number to.
    
    Returns:
        int: The number raised to the specified power.
    
    Takes a number and raises it to the specified power, returning the result.

    """

    return number ** power
...

# Calling the .__doc__ attribute of the function and printing the result.
>>> print(raise_to_power.__doc__)
Raise a number to an arbitrary power.

Parameters:
    number (int): The base number.
    power (int): The power to raise the base number to.

Returns:
    int: The number raised to the specified power.

Takes a number and raises it to the specified power, returning the result.

Istruzioni

Scriverai del codice che ti aiuterà a cucinare una lasagna favolosa dal tuo libro di ricette preferito.

Hai cinque attività, tutte legate alla preparazione della tua ricetta.


Note

Nel file stub abbiamo già scritto per te la prima definizione di funzione, ma dovrai scrivere tu le definizioni di funzione rimanenti. Dovrai anche definire tu tutte le costanti. Leggi con attenzione le righe di commento #TODO nel file stub. Quando hai finito un'attività, rimuovi il commento TODO.


1. Definisci come costante il tempo di cottura previsto in minuti

Definisci la costante EXPECTED_BAKE_TIME che rappresenta quanti minuti la lasagna dovrebbe cuocere in forno. Secondo il tuo libro di ricette, la lasagna dovrebbe stare in forno per 40 minuti:

>>> print(EXPECTED_BAKE_TIME)
40

2. Calcola il tempo di cottura rimanente in minuti

Completa la funzione bake_time_remaining() che prende come argomento i minuti effettivi che la lasagna ha già passato in forno e restituisce quanti minuti la lasagna deve ancora cuocere in base alla costante EXPECTED_BAKE_TIME.

>>> bake_time_remaining(30)
10

3. Calcola il tempo di preparazione in minuti

Definisci la funzione preparation_time_in_minutes() che prende come argomento il number_of_layers che vuoi aggiungere alla lasagna e restituisce quanti minuti impiegheresti a prepararli. Supponi che ogni strato richieda 2 minuti di preparazione.

>>> def preparation_time_in_minutes(number_of_layers):
        ...
        ...
        
>>> preparation_time_in_minutes(2)
4

4. Calcola il tempo totale trascorso (preparazione + cottura) in minuti

Definisci la funzione elapsed_time_in_minutes() che prende due parametri come argomenti:

  • number_of_layers (il numero di strati aggiunti alla lasagna)
  • elapsed_bake_time (il numero di minuti che la lasagna ha già passato a cuocere in forno).

Questa funzione dovrebbe restituire il totale dei minuti che hai passato in cucina a cucinare: il tempo di preparazione impiegato a impilare gli strati più il tempo che la lasagna ha passato a cuocere in forno.

>>> def elapsed_time_in_minutes(number_of_layers, elapsed_bake_time):
        ...
        ...
        
>>> elapsed_time_in_minutes(3, 20)
26

5. Aggiorna la ricetta con delle note

Torna sulla ricetta e aggiungi delle «note» sotto forma di docstring delle funzioni.

def elapsed_time_in_minutes(number_of_layers, elapsed_bake_time):
    """Calculate the elapsed cooking time.
    
    Parameters:
        number_of_layers (int): The number of layers in the lasagna.
        elapsed_bake_time (int): Time the lasagna has been baking in the oven.
    
    Returns:
        int: The total time elapsed (in minutes) preparing and baking.

    This function takes two integers representing the number of lasagna 
    layers and the time already spent baking the lasagna. It calculates 
    the total elapsed minutes spent cooking (preparing + baking).
    
    """
Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Python Exercism

Vuoi iniziare Le fantastiche lasagne di Guido?

Iscriviti a Exercism per imparare e padroneggiare Python con 17 concetti146 esercizi e il mentoring di persone reali, tutto gratis.