2012-07-11 17 views
16

Questa è una domanda forse stupida, ma guardando the mapping of operators to functions ho notato che non c'è alcuna funzione per esprimere l'operatore not in. All'inizio ho pensato che questo fosse probabilmente perché l'interprete semplicemente riordinava questo come not x in y, ma c'è una funzione per is not che sembra si dovrebbe comportare esattamente come not in. Mi manca qualcosa o l'operatore non esiste davvero?operatore python, nessun operatore per "non in"

Ecco un esempio veramente stupido in cui si potrebbe desiderare questo:

def compare_iter(a,b,func): 
    return [func(aa,bb) for aa,bb in zip(a,b)] 

my_compare=compare_iter(xx,yy,lambda x,y:x not in y) #lambda -- yuck 
my_compare=map(operator.not_,compare_iter(xx,yy,operator.contains) #extra map? grr... 
#it would be nice to do: my_compare=compare_iter(xx,yy,operator.not_contains) 

Naturalmente potrei scrivere il mio propria funzione per questo, ma poi si paga un prezzo in termini di efficienza, mentre il modulo operatore potrebbe spingere questo codice fuori di python e quindi eseguire più velocemente.

+0

In effetti, non si può "a non b" essere semplicemente riordinato in "non a è b"? – JAB

+0

Ci sono situazioni in cui un controllo per "non in" potrebbe essere eseguito più velocemente di un controllo per "in"? –

+1

@PaulManta dubbioso, poiché 'not in' è per definizione una ricerca esauriente. –

risposta

14

Qui non è necessaria un'altra funzione. not in è l'inverso di in, in modo da avere le seguenti mappature:

obj in seq => contains(seq, obj) 

obj not in seq => not contains(seq, obj) 

hai ragione questo non è coerente con is/is not, in quanto test d'identità dovrebbero essere simmetrici. Questo potrebbe essere un artefatto di design.

+1

Nel pensare a questo, mi sembra che un altro operatore * dovrebbe * essere necessario. 'x> y' non implica (necessariamente)' not (x <= y) 'in python. Perché il test per il contenimento dovrebbe essere diverso? – mgilson

3

Potete trovare la seguente funzione e lo smontaggio di essere utile per comprendere gli operatori:

>>> def test(): 
     if 0 in(): pass 
     if 0 not in(): pass 
     if 0 is(): pass 
     if 0 is not(): pass 
     return None 

>>> dis.dis(test) 
    2   0 LOAD_CONST    1 (0) 
       3 LOAD_CONST    2 (()) 
       6 COMPARE_OP    6 (in) 
       9 POP_JUMP_IF_FALSE  15 
      12 JUMP_FORWARD    0 (to 15) 

    3  >> 15 LOAD_CONST    1 (0) 
      18 LOAD_CONST    3 (()) 
      21 COMPARE_OP    7 (not in) 
      24 POP_JUMP_IF_FALSE  30 
      27 JUMP_FORWARD    0 (to 30) 

    4  >> 30 LOAD_CONST    1 (0) 
      33 LOAD_CONST    4 (()) 
      36 COMPARE_OP    8 (is) 
      39 POP_JUMP_IF_FALSE  45 
      42 JUMP_FORWARD    0 (to 45) 

    5  >> 45 LOAD_CONST    1 (0) 
      48 LOAD_CONST    5 (()) 
      51 COMPARE_OP    9 (is not) 
      54 POP_JUMP_IF_FALSE  60 
      57 JUMP_FORWARD    0 (to 60) 

    6  >> 60 LOAD_CONST    0 (None) 
      63 RETURN_VALUE   
>>> 

Come si può vedere, c'è una differenza di ogni operatore; e i loro codici (in ordine) sono 6, 7, 8 e 9.

+2

Sì, ma se non si esegue '0 in()', lo traduce in '0 non in()' - Questo mi fa pensare ancora di più che ci dovrebbe essere un operatore corrispondente nel modulo operatore come 'not in' è chiaramente un operatore distinto (e anche preferito) per l'interprete ... – mgilson

+2

@mgilson: l'ho notato solo io. Ho pensato che sarebbe stato il contrario, ma come è ora mi trovo d'accordo con il tuo punto di vista. È interessante notare che non riesco a trovare alcuna discussione sull'inclusione di 'not in' come membro di' operator' nelle mailing list ufficiali di Python, nonostante ci sia una discussione sull'utilità di questo. – JAB

+1

@JAB, potresti pubblicare un link ad alcune discussioni sull'utilità? (Per me questa domanda era per lo più accademica, mi piacerebbe vedere cosa pensano le altre persone dei casi d'uso reali) C'è un modo per richiederlo? – mgilson