2012-07-11 11 views
16

Esta es una pregunta posiblemente tonta, pero al mirar the mapping of operators to functions noté que no hay una función para expresar el operador not in. Al principio pensé que esto era probablemente porque el intérprete simplemente reordena esto para que sea not x in y, pero hay una función para is not que parece que debería comportarse exactamente igual que not in. ¿Me estoy perdiendo algo, o ese operador realmente no existe?operador de python, no hay operador para "no entrar"

Aquí hay un ejemplo muy estúpida en la que podría querer esto:

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) 

Por supuesto que podría escribir mi propia función para esto, pero entonces pagar un precio en la eficiencia mientras que el módulo operador podría empujar este código a cabo de python y, por lo tanto, ejecutar más rápido.

+0

De hecho, ¿no se pudo reordenar 'a a b' simplemente' not a is b'? – JAB

+0

¿Hay alguna situación en la que un control de 'no en 'podría realizarse más rápido que un cheque para' in'? –

+1

@PaulManta dudoso, ya que 'no en 'es, por definición, una búsqueda exhaustiva. –

Respuesta

14

Aquí no es necesaria otra función. not in es la inversa de in, por lo que tiene las siguientes asignaciones:

obj in seq => contains(seq, obj) 

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

tienes razón esto no es consistente con is/is not, ya que las pruebas de identidad debe ser simétrica. Esto podría ser un artefacto de diseño.

+1

Al pensar en esto, me parece que otro operador * debería * ser necesario. 'x> y' no implica (necesariamente)' not (x <= y) 'en python. ¿Por qué las pruebas de contención deben ser diferentes? – mgilson

3

Usted puede encontrar la siguiente función y desmontaje de ser útil para la comprensión de los operadores:

>>> 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   
>>> 

Como se puede ver, hay una diferencia en cada operador; y sus códigos (en orden) son 6, 7, 8 y 9.

+2

Sí, pero si lo hace 'no 0 en()', lo traduce en '0 no en()' - Esto me hace pensar aún más que debería haber un operador correspondiente en el módulo del operador como 'no en' es claramente un operador distinto (e incluso preferido) para el intérprete ... – mgilson

+2

@mgilson: Me acabo de dar cuenta de eso. Pensé que sería al revés, pero tal como está, ahora estoy de acuerdo con tu punto. Curiosamente, parece que no encuentro ninguna discusión sobre la inclusión de 'no en' como miembro de' operator' en las listas de correo oficiales de Python, a pesar de que hay una discusión sobre su utilidad. – JAB

+1

@JAB, ¿podría publicar un enlace a algunas de las discusiones sobre la utilidad? (Esta pregunta fue principalmente académica para mí, me encantaría ver lo que otras personas piensan sobre los casos de uso reales) ¿Hay alguna manera de solicitar que se agregue? – mgilson