Python Auto Formatter: Autopep8 vs. Black (e alcuni consigli pratici)
Ecco la conclusione: preferisco il nero come strumento di formattazione automatica, ma ci sono alcuni suggerimenti pratici (alla fine) che dovresti tenere a mente e funziona meglio in parallelo con altri strumenti come isort.
introduzione
Autopep8 e Black sono entrambi ottimi strumenti per formattare automaticamente il codice Python in modo che sia conforme alla guida di stile PEP 8 . Black ha 30.4k stelle su GitHub ed è probabilmente lo strumento più popolare nel suo genere, mentre autopep8 ha 4.2k stelle.
Una delle principali differenze è che il nero è un formattatore supponente, il che significa che converte sempre l'intera base di codice nel proprio stile, mentre autopep8 conserva lo stile di input in una certa misura e corregge solo le parti necessarie.
Ho utilizzato entrambi gli strumenti nel mio lavoro e vorrei condividere con voi perché preferisco il nero rispetto ad autopep8.
Problemi con autopep8
1. Smista le importazioni in modo aggressivo
Alcuni potrebbero vederlo come una buona cosa, tuttavia, secondo me un buon strumento dovrebbe concentrarsi su una cosa e solo una cosa. In quanto strumento di formattazione, non dovrebbe tentare di modificare l'ordine del codice e, in effetti, a volte può causare problemi.
Consideriamo l'esempio seguente. Anche se sys.path.appendgeneralmente non è una buona pratica, ma diciamo solo che vogliamo davvero fare qualcosa prima di importare il resto dei moduli.
Autopep8 riscriverebbe lo script nel modo seguente:
E questo è problematico. Un altro esempio che mi viene in mente è che se vogliamo abilitare il backend di matplotlib per un terminale Linux, dovremmo impostare il backend matplotlib.use("agg") prima di pyplot import from matplotlib import pyplot as plt.
Al contrario, il nero non cambierà il codice di esempio sopra. Il nero fa solo la formattazione e la semantica del codice rimane esattamente la stessa. In altre parole, il nero non ordina le tue importazioni e non cambia l'ordine del tuo codice. (e possiamo lasciare il compito di ordinare le importazioni per un altro ottimo strumento isort , continua a leggere!)
Puoi ancora risolvere il problema aggiungendo # nopep8ad alcuni frammenti del tuo codice, dicendo esplicitamente ad autopep8 di non toccarlo:
Funziona in questo caso, ma ho scoperto che la # nopep8regola di esclusione non viene applicata ai commenti, ad esempio autopep8 convertirà comunque quanto segue ### some comment # nopep8in # some comment # nopep8.
D'altra parte, black non modifica commenti e docstring e puoi escludere parte del tuo codice dalla formattazione aggiungendo due righe di commento # fmt: offe # fmt: onprima e dopo il tuo blocco di codice.
Ad ogni modo, non è molto Pythonic, giusto?
2. Non applica correttamente il rientro
L'indentazione predefinita di Autopep8 è impostata sulla stessa dimensione della scheda dell'editor e puoi specificare il valore passando l'opzione autopep8 --indent-size 4 myfile.py. Va tutto bene, tuttavia, autopep8 solo questo valore di input per impostare il rientro per l'inizio di ogni istruzione, ma la dimensione del rientro tra parentesi è sempre impostata sulla dimensione di tabulazione predefinita.
Diamo un'occhiata a questo esempio, in cui il rientro del codice è 1 e la dimensione di tabulazione predefinita del mio editor è 4.
Dopo aver impostato l'indentazione su 3 con autopep8 autopep8 --indent-size 3 format_02_raw.py -i (-i significa sul posto) , otteniamo quanto segue:
Possiamo vedere che l'indentazione nella prima funzione è impostata correttamente su 3, ma qualsiasi cosa tra parentesi (in questo caso, l'istruzione print e la matrice) è invece impostata sulla dimensione di tabulazione predefinita 4.
L'ho scoperto perché la dimensione della scheda predefinita nel mio ambiente di lavoro è 2 e preferisco il rientro di 4. Potrebbe sembrare banale, ma perché rischiare l'incoerenza non necessaria? Il nero non ti consente di configurare la dimensione del rientro, poiché imposta sempre il rientro su 4 in tutti i punti, cosa che non mi dispiace affatto.
Usare il nero nel modo giusto
Il nero implementa il proprio stile, che ad alcune persone piace e ad altre no. Mi piace molto perché è generalmente molto pulito e leggibile, ma ci sono due cose da tenere a mente.
1. Usa una virgola finale
L'esempio seguente mostra probabilmente uno dei motivi più comuni per cui ad alcune persone non piace il nero. Diamo un'occhiata al prima e al dopo:
È fastidioso, ma prima che ti arrabbi, apportiamo alcune piccole modifiche al codice e vediamo come il nero cambia il suo comportamento:
Sì, il nero utilizza le virgole finali per decidere se gli elementi verranno raggruppati insieme o rimarranno in nuove righe. Se un elemento simile a un array termina senza una virgola finale, sia esso un elenco, una matrice o un dizionario, il nero cerca sempre di deformarlo in una riga; se supera la lunghezza della riga, il nero inserisce il suo contenuto in nuove righe e aggiunge una virgola finale per te . Se c'è una virgola finale nell'elemento, il nero separa il suo contenuto in nuove righe per te .
In breve, ci sarà sempre una virgola finale ogni volta che il contenuto di un elemento simile a un array si trova in nuove righe. Penso che questo abbia senso, e in generale le virgole finali sono una buona pratica in quanto rendono il codice più facile da mantenere, oltre a generare pulizia git diffquando si apportano modifiche. Quindi, se non vuoi che il nero racchiuda il tuo codice in una riga, aggiungi una virgola alla fine!
Suggerimenti bonus: quando scrivo query SQL, scrivo
SELECT column_a
,column_b
,column_c
FROM some_table
SELECT column_a,
column_b,
column_c
FROM some_table
2. Se necessario, specificare la lunghezza della linea
L'unica cosa che non mi piace dello stile del codice nero finora riguarda le lunghe istruzioni if, come mostra l'esempio seguente:
Ha rafforzato la coerenza ma ha sacrificato la leggibilità. La lunghezza della riga predefinita di Black è 88, ma a volte ho istruzioni leggermente più lunghe e non voglio che siano formattate in quel modo.
La mia soluzione è consentire una lunghezza della linea leggermente più lunga. Possiamo specificare la lunghezza della linea usando --line-lengtho -lflag, e se impostiamo la lunghezza della linea su 100 black -l 100 format_05_raw.py, l'esempio precedente non verrà riformattato. Dalla mia esperienza, una lunghezza di 100 righe si adatterebbe alla maggior parte delle dichiarazioni lunghe pur mantenendo una buona leggibilità del codice (anche se dovresti davvero considerare di riscrivere la tua dichiarazione se è lunga più di 100 caratteri), ma ovviamente spetta a ogni squadra decidere .
Anche Autopep8 ha un tale flag --max-line-length, tuttavia, poiché autotpep8 tende a preservare lo stile del codice originale, il risultato della formattazione è molto meno sensibile alla lunghezza della riga specificata rispetto al nero.
3. Usa il nero con isort
Come accennato in precedenza, il nero non ordina le tue importazioni e possiamo usare isort (5.4k stelle su GitHub) per farlo. Diamo un'occhiata a un rapido esempio di cosa può fare isort:
È pulito e non rovina il nostro sys.path.appendesempio.
Si noti che ci sono alcune lievi differenze tra il modo in cui isort e black organizzano le importazioni, e possiamo dire a isort di ordinare le importazioni in modo conforme allo stile del codice nero isort --profile black format_06_raw.py.
Ora abbiamo un flusso di lavoro piuttosto buono: usa isort per ordinare prima le importazioni, quindi usa black per formattare il nostro codice. Possiamo combinare i due passaggi insieme in Makefile:
format:
isort --profile black src/
black -l 100 src/
Conclusione
In questo articolo abbiamo confrontato due popolari strumenti di formattazione automatica in Python: autopep8 e black. Ho spiegato perché preferisco il nero e come mi piace usarlo, e spero che questo sia utile.
Questa è anche la prima volta che scrivo un articolo su Medium, sentiti libero di darmi un applauso se ti piace e non dimenticare di lasciare i tuoi commenti qui sotto, e alla prossima!

![Che cos'è un elenco collegato, comunque? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































