No, questo non è sicuramente Pythonic. Molte delle decisioni prese lungo il percorso sono state appositamente per scoraggiare questo tipo di codifica.
Il modo giusto di scrivere questo è il modo più ovvio:
if verbose:
print(stuff)
Oppure, se il calcolo stuff
di per sé non è costoso/pericolosi/irrevocabile, basta avvolgere print
in una funzione che controlla la bandiera:
def printv(*args, **kwargs):
if verbose:
print(*args, **kwargs)
... così si può solo fare questo, che è quanto di più conciso, come si sta andando ad ottenere:
printv(stuff)
Oppure, ancora meglio, utilizzare il modulo logging
invece di reinventare la ruota.
Ma cosa succede se stuff
è costoso, e si vuole veramente salvare una linea?
Bene, probabilmente non è necessario salvare una riga, e così facendo si sacrifica sempre la leggibilità per brevità; "Conteggi di leggibilità" è una parte fondamentale di the Zen of Python.Ma Python non consentono di mettere una suite con una linea sulla stessa riga della condizione:
if verbose: print(stuff)
Come PEP 8 lo mette, "a volte va bene", ma è "generalmente scoraggiato". Come ha scritto Guido in una mail sulla mailing list delle idee, "Se devi salvare una riga, usa una frase se una riga piuttosto che qualcosa di 'intelligente', ma se devi salvare una riga, probabilmente non voglio leggi il tuo codice. "
Se si desidera che questo in un'espressione (che non si dovrebbe, come spiegherò più avanti), o se si vuole tecnicamente follow PEP 8 alla lettera, mentre palesemente violando lo spirito:
print(stuff) if verbose else None
Quindi, cosa c'è di Pythonic a riguardo?
Per prima cosa, si sta utilizzando il risultato di print
in un'espressione, anche se print
non ha risultati utili e viene chiamato solo per i suoi effetti collaterali. Questo è fuorviante.
E in generale, Python ha solo un effetto collaterale per riga, e si verifica il più a sinistra possibile, il che rende più facile scremare il codice e vedere cosa sta cambiando. Ciò è rafforzato dal forte divario tra le dichiarazioni e le espressioni (e, ad esempio, i compiti sono dichiarazioni), dai metodi con effetti collaterali che restituiscono idiomaticamente None
anziché self
e così via.
Ma anche ignorare tutto questo, usando and
e or
solo per cortocircuiti, piuttosto che per i loro risultati, è potenzialmente confuso e, almeno per alcune persone, brutto. Ecco perché è stata aggiunta l'espressione ternaria (spam if eggs else beans
): per impedire alle persone di scrivere eggs and spam or beans
. Perché è confuso? Per prima cosa, in realtà non legge affatto l'inglese, a meno che tu non stia leggendo più codice Perl che inglese corrente. Per un altro, è molto facile usare per errore un valore valido che è falso; sai di non farlo, e per controllarlo, quando vedi un if
, ma non lo fai qui. Si noti inoltre che lo print(stuff) if verbose else None
rende esplicito che si sta creando un valore con cui non si fa nulla; esplicito è sempre meglio di implicito, ma soprattutto quando fai qualcosa di non comune.
Infine, per quanto riguarda le prestazioni: (a) chi se ne frega, e (b) il motivo per cui non misura, invece di tentare di indovinare leggendo bytecode che non capisci?
In [511]: quiet = True
In [512]: %timeit quiet or None
10000000 loops, best of 3: 48.2 ns per loop
In [513]: verbose=False
In [514]: %timeit if verbose: pass
10000000 loops, best of 3: 38.5 ns per loop
Così ci si va, nel caso-pass fast food, la dichiarazione if
è in realtà circa il 20% più veloce, non più lento e sono entrambi così velocemente che è improbabile che possa influenzare mai il vostro programma in ogni caso . Se stai facendo questo un miliardo di volte in un circuito chiuso e hai bisogno di spremere quella performance, vorrai sollevare il resto del ciclo, anche se questo significa ripetersi con due cloni vicini dello stesso codice (specialmente considerando che un loop senza lo print
s è più probabile che si adatti alla cache, ecc.).
Se vuoi sapere perché, dovresti esaminare l'implementazione di quei bytecode sulla particolare versione dell'implementazione particolare che ti interessa ... ma molto probabilmente, dovresti fare un extra POP_TOP
invece di avere una fusione nell'operazione precedente fa parte della differenza.
Si prega di non farlo. – PaulMcG
Penso che tu abbia chiesto :) –
Non sembra più gradito a nessuno che non sia un programmatore PHP. Per quanto riguarda il salvataggio di una linea, c'è una carenza di linee in cui vivi? Abbiamo extra. –