4 potenti funzionalità Python manca ancora

Python è un linguaggio vivente, in costante sviluppo per stare al passo con i tempi. La Python Software Foundation non sta solo apportando aggiunte alla libreria standard e all'implementazione di riferimento CPython, ma introduce anche nuove funzionalità e perfezionamenti al linguaggio stesso.

Ad esempio, Python 3.8 ha introdotto una nuova sintassi per gli assegnamenti in linea (l '"operatore tricheco") che rende alcune operazioni più concise. Un altro miglioramento della sintassi approvato di recente, il pattern matching, renderà più facile scrivere codice che valuta uno dei tanti casi possibili. Entrambe queste funzionalità sono state ispirate dalla loro presenza e utilità in altre lingue.

E sono solo due di una serie di utili funzionalità che potrebbero essere aggiunte a Python per rendere il linguaggio più espressivo, più potente, più adatto al mondo della programmazione moderna. Cos'altro potremmo desiderare? Ecco altre quattro funzionalità del linguaggio che potrebbero aggiungere qualcosa di valore reale a Python: due che potremmo effettivamente ottenere e due probabilmente no. 

Costanti vere

Python non ha davvero il concetto di un valore costante. Oggi, le costanti in Python sono per lo più una questione di convenzione. L'utilizzo di un nome in maiuscolo e in maiuscolo, ad esempio, DO_NOT_RESTART indica che la variabile deve essere una costante. Allo stesso modo, l' typing.Final annotazione del  tipo fornisce un suggerimento a linters che un oggetto non dovrebbe essere modificato, ma non lo impone in fase di esecuzione.

Perché? Perché la mutabilità è profondamente radicata nei comportamenti di Python. Quando si assegna un valore a una variabile, ad esempio,  x=3 si crea un nome nello spazio dei nomi locale  xe lo si punta su un oggetto nel sistema che ha il valore intero  3. Python presume in ogni momento che i nomi siano mutabili, che qualsiasi nome possa puntare a qualsiasi oggetto. Ciò significa che ogni volta che viene usato un nome, Python si prende la briga di cercare quale oggetto sta puntando. Questo dinamismo è uno dei motivi principali per cui Python viene eseguito più lentamente rispetto ad altri linguaggi. Il dinamismo di Python offre grande flessibilità e praticità, ma va a scapito delle prestazioni di runtime.

Un vantaggio di avere vere dichiarazioni di costanti in Python sarebbe una certa riduzione della frequenza delle ricerche di oggetti che avvengono durante il runtime, e quindi migliori prestazioni. Se il runtime sa in anticipo che un dato valore non cambia mai, non deve cercare i suoi binding. Ciò potrebbe anche fornire una via per ulteriori ottimizzazioni di terze parti, come i sistemi che generano codice nativo della macchina dalle app Python (Cython, Nuitka).

Tuttavia, le costanti vere rappresenterebbero un cambiamento importante e molto probabilmente un cambiamento incompatibile con le versioni precedenti. Sarebbe anche oggetto di dibattito se le costanti arrivassero attraverso una nuova sintassi - per esempio, il $ simbolo non ancora utilizzato  - o come un'estensione del modo esistente di Python di dichiarare i nomi. Infine, c'è la più ampia questione filosofica se le costanti vere abbiano o meno un senso in un linguaggio in cui il dinamismo è stato una parte importante del fascino.

In breve, è possibile che vedremo delle vere costanti in Python, ma sarebbe un cambiamento importante.

Vero sovraccarico e generici

In molte lingue, è possibile scrivere più versioni della stessa funzione per lavorare con diversi tipi di input. Ad esempio, una  to_string() funzione potrebbe avere diverse implementazioni per la conversione da numeri interi, numeri in virgola mobile o altri oggetti, ma condivideranno lo stesso nome per comodità. "Sovraccarico" o "generici" rendono più facile scrivere software robusto, poiché è possibile scrivere metodi generici per processi comuni piuttosto che utilizzare un metodo specifico per un determinato tipo.

Python ti consente di usare un nome di funzione per svolgere il lavoro di molte, ma non definendo più istanze di una funzione. È possibile definire un nome solo una volta in un determinato ambito e associarlo a un solo oggetto alla volta, quindi non è possibile avere più versioni di una singola funzione con lo stesso nome.

Ciò che gli sviluppatori Python in genere fanno per aggirare questo problema è utilizzare built-in come  isinstance() o  type() per determinare il tipo di variabile inviata a una funzione, quindi agire in base al tipo. A volte ciò comporta l'invio a una versione specifica del tipo di una funzione nascosta. Ma questo approccio rende difficile per altri sviluppatori estendere la tua funzione a meno che tu non esca dal tuo modo di renderla estensibile, ad esempio inviando a metodi all'interno di una classe, che potrebbe essere sottoclasse.

PEP 3124, avanzato nell'aprile 2007, ha proposto un meccanismo per decorare le funzioni per indicare che potevano essere sovraccaricate. La proposta è stata rinviata anziché essere respinta a titolo definitivo, il che significa che l'idea era fondamentalmente solida, ma non era il momento giusto per attuarla. Un fattore che potrebbe accelerare l'adozione del sovraccarico in Python - o far sì che l'idea venga completamente abbandonata - è l'implementazione del sistema di corrispondenza dei modelli recentemente proposto.

In teoria, il pattern matching potrebbe essere utilizzato sotto il cofano per gestire la spedizione di sovraccarico. Tuttavia, la corrispondenza dei modelli potrebbe anche essere fornita come motivazione per non implementare i generici in Python, poiché fornisce già un modo elegante per inviare operazioni basate sulle firme dei tipi.

Quindi un giorno potremmo ottenere un vero sovraccarico in Python, oppure i suoi vantaggi potrebbero essere sostituiti da altri meccanismi.

Ottimizzazione della ricorsione della coda

Molti compilatori di linguaggio utilizzano ottimizzazioni di ricorsione in coda, in cui le funzioni che si chiamano non creano nuovi stack frame nell'applicazione e quindi rischiano di far saltare in aria lo stack se vengono eseguite per troppo tempo. Python non lo fa, e in effetti i suoi creatori si sono costantemente dichiarati contrari.

Uno dei motivi è che gran parte di Python, dall'interno verso l'esterno, utilizza l'  iterazione  anziché la  ricorsione  : generatori, coroutine e così via. In questo caso, significa usare una funzione con un ciclo e una struttura a stack invece di un meccanismo ricorsivo. Ogni chiamata del ciclo può essere salvata in uno stack per creare una nuova ricorsione e rimossa dallo stack al termine della ricorsione.

Gli sviluppatori Python sono incoraggiati a utilizzare questi modelli invece della ricorsione, quindi sembra che ci siano poche speranze per l'ottimizzazione della ricorsione. Le possibilità qui non sono affatto probabili, poiché gli idiomi di Python supportano altre soluzioni.

Lambda multilinea

Lambdas, o funzioni anonime, sono entrate in Python solo dopo qualche resistenza da parte del creatore del linguaggio Guido van Rossum. Poiché i lambda di Python esistono ora, sono altamente vincolati: consentono solo di utilizzare una singola espressione (essenzialmente, qualsiasi cosa a destra di un segno di uguale in un'operazione di assegnazione) come corpo della funzione. Se vuoi un blocco completo di affermazioni, suddividile e crea una funzione effettiva da esse.

Il motivo è dovuto al design del linguaggio come lo vede van Rossum. Come scrisse van Rossum nel 2006, “Trovo   inaccettabile qualsiasi soluzione che incorpori un blocco basato sull'indentazione nel mezzo di un'espressione. Dal momento che trovo ugualmente inaccettabile la sintassi alternativa per il raggruppamento di istruzioni (ad esempio parentesi graffe o parole chiave di inizio / fine), questo rende praticamente un lambda multilinea un puzzle irrisolvibile. "

In altre parole, il problema non è tecnico, ma la mancanza di una sintassi per lambda multilinea che integri l'estetica esistente della sintassi Python. Probabilmente non c'è modo di farlo che non implichi la creazione di un caso speciale e un linguaggio che accumula casi speciali tende a diventare sgradevole da usare. Fino a quando non apparirà un unicorno del genere, dovremo solo accontentarci di funzioni definite separatamente.

I lambda multilinea probabilmente non si verificano in Python.

Ulteriori informazioni su Python:

  • Python 3.9: cosa c'è di nuovo e migliore
  • Le migliori nuove funzionalità di Python 3.8
  • Migliore gestione dei progetti Python con Poetry
  • Virtualenv e venv: spiegazione degli ambienti virtuali Python
  • Python virtualenv e venv cosa fare e cosa non fare
  • Spiegazione del threading e dei sottoprocessi di Python
  • Come utilizzare il debugger Python
  • Come usare timeit per profilare il codice Python
  • Come usare cProfile per profilare il codice Python
  • Inizia con async in Python
  • Come usare asyncio in Python
  • Come convertire Python in JavaScript (e viceversa)
  • Python 2 EOL: come sopravvivere alla fine di Python 2
  • 12 Pythons per ogni esigenza di programmazione
  • 24 librerie Python per ogni sviluppatore Python
  • 7 dolci IDE Python che potresti aver perso
  • 3 principali carenze di Python e le loro soluzioni
  • 13 framework web Python a confronto
  • 4 framework di test Python per schiacciare i tuoi bug
  • 6 fantastiche nuove funzionalità di Python da non perdere
  • 5 distribuzioni Python per padroneggiare l'apprendimento automatico
  • 8 fantastiche librerie Python per l'elaborazione del linguaggio naturale
  • 6 librerie Python per l'elaborazione parallela
  • Cos'è PyPy? Python più veloce senza dolore
  • Cos'è Cython? Python alla velocità di C