Python `if x is None` o` if not x is None`?


747

Ho sempre pensato che la if not x is Noneversione fosse più chiara, ma la guida di stile di Google e PEP-8 usano entrambi if x is not None. C'è qualche differenza di prestazione minore (suppongo di no) e c'è un caso in cui uno non si adatta davvero (rendendo l'altro un chiaro vincitore per la mia convention)? *

* Mi riferisco a qualsiasi singleton, piuttosto che solo None.

... per confrontare i singoli come Nessuno. L'uso è o non è.


8
is notè un operatore a sé stante. Come !=. Se si preferisce not x is Noneallora la vostra dovrebbe anche preferire not a == bsopra a != b.
Tomasz Gandor,

@TomaszGandor Non ho più questa opinione su not x is None(le risposte qui mi hanno convinto) - vale comunque la pena notare che not a == bè lo stile preferito in Python, rispetto a a != b.
Orokusaki,

4
@orokusaki è not a == bdavvero lo stile preferito? Non l'ho mai visto fare in questo modo e ovunque sembri che tutte le persone lo usino !=.
Mike - SMT

2
@orokusaki in Python leggibilità conta quindi è uno stile preferito per utilizzare un solo operatore !=, invece di due operatori not, ==.
Jeyekomon,

Risposte:


995

Non ci sono differenze di prestazioni, poiché si compilano con lo stesso bytecode:

Python 2.6.2 (r262:71600, Apr 15 2009, 07:20:39)
>>> import dis
>>> def f(x):
...    return x is not None
...
>>> dis.dis(f)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE
>>> def g(x):
...   return not x is None
...
>>> dis.dis(g)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE

Stilisticamente, provo ad evitare not x is y. Sebbene il compilatore lo tratterà sempre come not (x is y), un lettore umano potrebbe fraintendere il costrutto come (not x) is y. Se scrivo, x is not yallora non c'è ambiguità.


103
A meno che lo stesso lettore umano pensasse che fosse x is (not y). Ma tendo ad essere d'accordo con te per il tuo altro ragionamento.
Etaoin,

24
inoltre "non è" è meno ambiguo in questo contesto "se a non è Nessuno eb b è Nessuno:" vs "se non è a è Nessuno e b è Nessuno:"
Gordon Wrigley,

45
l'operatore dovrebbe essere "non"
bean

217

Sia la guida di stile di Google che quella di Python è la migliore pratica:

if x is not None:
    # Do something about x

L'uso not xpuò causare risultati indesiderati.

Vedi sotto:

>>> x = 1
>>> not x
False
>>> x = [1]
>>> not x
False
>>> x = 0
>>> not x
True
>>> x = [0]         # You don't want to fall in this one.
>>> not x
False

Potresti essere interessato a vedere quali valori letterali vengono valutati in Trueo Falsein Python:


Modifica per il commento qui sotto:

Ho appena fatto qualche altro test. not x is Nonenon nega xprima e poi rispetto a None. In effetti, sembra che l' isoperatore abbia una precedenza maggiore quando viene utilizzato in questo modo:

>>> x
[0]
>>> not x is None
True
>>> not (x is None)
True
>>> (not x) is None
False

Pertanto, not x is Nonesecondo la mia sincera opinione, è meglio evitare.


Altre modifiche:

Ho appena fatto più test e posso confermare che il commento di bukzor è corretto. (Almeno, non sono stato in grado di dimostrarlo diversamente.)

Questo significa che if x is not Noneha il risultato esatto come if not x is None. Sono corretto. Grazie bukzor.

Tuttavia, la mia risposta è ancora valida: usa il convenzionaleif x is not None .:]


131

Il codice deve essere scritto per essere comprensibile prima al programmatore e in secondo luogo al compilatore o all'interprete. Il costrutto "non è" assomiglia all'inglese più da vicino di "non è".


33

Python if x is not Noneo if not x is None?

TLDR: il compilatore bytecode li analizza entrambi x is not None, quindi, per motivi di leggibilità, utilizzare if x is not None.

leggibilità

Usiamo Python perché apprezziamo cose come la leggibilità umana, l'usabilità e la correttezza di vari paradigmi di programmazione rispetto alle prestazioni.

Python ottimizza per la leggibilità, soprattutto in questo contesto.

Analisi e compilazione del Bytecode

I not vincoli sono più deboli di is, quindi non c'è alcuna differenza logica qui. Vedi la documentazione :

Operatori ise is nottest per l'identità dell'oggetto: x is yè vero se e solo se xey sono lo stesso oggetto. x is not yproduce il valore della verità inversa.

Questo is notè specificamente previsto nella grammatica di Python come miglioramento della leggibilità per la lingua:

comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'

E quindi è anche un elemento unitario della grammatica.

Certo, non viene analizzato lo stesso:

>>> import ast
>>> ast.dump(ast.parse('x is not None').body[0].value)
"Compare(left=Name(id='x', ctx=Load()), ops=[IsNot()], comparators=[Name(id='None', ctx=Load())])"
>>> ast.dump(ast.parse('not x is None').body[0].value)
"UnaryOp(op=Not(), operand=Compare(left=Name(id='x', ctx=Load()), ops=[Is()], comparators=[Name(id='None', ctx=Load())]))"

Ma poi il compilatore di byte tradurrà effettivamente not ... isin is not:

>>> import dis
>>> dis.dis(lambda x, y: x is not y)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_FAST                1 (y)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE
>>> dis.dis(lambda x, y: not x is y)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_FAST                1 (y)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE

Quindi, per motivi di leggibilità e utilizzo della lingua come previsto, si prega di utilizzare is not.

Non usarlo non è saggio.


"I notlegami sono più deboli di is, quindi non c'è alcuna differenza logica qui" - tranne per il fatto che Python non deve imporre identità logiche e algebriche da conservare (nessuna ragione intrinseca per (1 + 2)*3valutare lo stesso di 1*3 + 2*3). Qui a quanto pare Python sta barando e ottimizzando UNARY_NOT.
Alexey,

30

La risposta è più semplice di quanto la gente la stia realizzando.

Non c'è alcun vantaggio tecnico in entrambi i casi e "x is not y" è ciò che usano tutti gli altri , il che lo rende il chiaro vincitore. Non importa che "assomigli più all'inglese" o no; tutti lo usano, il che significa che ogni utente di Python - anche gli utenti cinesi, la cui lingua Python non assomiglia affatto - lo capiranno a colpo d'occhio, dove la sintassi leggermente meno comune richiederà un paio di cicli cerebrali extra per analizzare.

Non essere diverso solo per il gusto di essere diverso, almeno in questo campo.


11

L' is notoperatore è preferito piuttosto che negare il risultato isper motivi stilistici. " if x is not None:" legge esattamente come l'inglese, ma " if not x is None:" richiede la comprensione della precedenza dell'operatore e non legge come l'inglese.

Se c'è una differenza di prestazioni, i miei soldi sono accesi is not, ma questo non è quasi certamente la motivazione per la decisione di preferire quella tecnica. Ovviamente dipenderà dall'implementazione. Poiché isnon è sostituibile, dovrebbe comunque essere facile ottimizzare ogni distinzione.


9

Personalmente, io uso

if not (x is None):

che viene immediatamente compreso senza ambiguità da ogni programmatore, anche da quelli non esperti nella sintassi di Python.


5
Un giusto argomento con cui concordo, ma credo che l'argomento di seguire lo stile idiomatico sia più forte.
clacke,

2

if not x is Noneè più simile ad altri linguaggi di programmazione, ma if x is not Nonesuona decisamente più chiaro (ed è grammaticalmente più corretto in inglese) per me.

Detto questo, sembra che per me sia più una preferenza.


0

Preferirei la forma più leggibile x is not y di quanto penserei come scrivere alla fine la precedenza di gestione del codice degli operatori per produrre codice molto più leggibile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.