TypeChecking per una funzione che restituisce None

Aug 23 2020

Considera l'implementazione ricorsiva della funzione fattoriale -

from typing import Optional

def factorial(val: int) -> Optional[int]:
    if val<0:
        return None
    if val==0:
        return 1
    return val*factorial(val-1)


if __name__ == "__main__":
    print(square_root(3))

Sto usando mypyper il controllo del tipo statico. Mi genera il seguente errore:

type-hints.py:8: error: Unsupported operand types for * ("int" and "None")
type-hints.py:8: note: Right operand is of type "Optional[int]"
Found 1 error in 1 file (checked 1 source file)

Ho provato a utilizzare Optionalcome da questa domanda StackOverflow. Ma non sembra funzionare. Eventuali suggerimenti?

Domande -

  1. Come specificare il tipo restituito quando la funzione restituisce None?
  2. Mi sembra un po' sorprendente che mypy sia stata in grado di immaginare una situazione in cui potrebbe verificarsi la moltiplicazione tra inte . NoneAd esempio, se rimuovo intl' argomento val e chiamo la funzione fattoriale con un float, potrebbe generare tale errore.

Risposte

2 MisterMiyagi Aug 23 2020 at 03:01

MyPy ha ragione sul fatto che la funzione non è ben tipizzata. La firma della funzione è (int) -> Optional[int], rendendola val*factorial(val-1) eventualmente errata. Ciò Nonesi verifica solo per informazioni val < 0di tipo non statico.

Invece di restituire Noneun input non valido, solleva un'eccezione. Ciò rende la funzione staticamente ben tipizzata, senza rimuovere la gestione degli errori.

def factorial(val: int) -> int:
    if val<0:
        raise ValueError("factorial() not defined for negative values")
    if val==0:
        return 1
    return val*factorial(val-1)

Se per qualche motivo è necessario restituire None, annotare esplicitamente che l'espressione è valida e non necessita di controllo.

def factorial(val: int) -> int:
    if val<0:
        return None
    if val==0:
        return 1
    return val*factorial(val-1)  # type: ignore