“X não está em y” ou “não é x em y”

97

Ao testar a associação, podemos usar:

x not in y

Ou alternativamente:

not x in y

Pode haver muitos contextos possíveis para esta expressão dependendo de xe y. Pode ser para uma verificação de substring, associação de lista, existência de chave de ditado, por exemplo.

  • As duas formas são sempre equivalentes?
  • Existe uma sintaxe preferida?
wim
fonte

Respostas:

112

Eles sempre dão o mesmo resultado.

Na verdade, not 'ham' in 'spam and eggs'parece ter um caso especial para executar uma única operação "não ativada", em vez de uma operação "interna" e, em seguida, negar o resultado:

>>> import dis

>>> def notin():
    'ham' not in 'spam and eggs'
>>> dis.dis(notin)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               7 (not in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE    

>>> def not_in():
    not 'ham' in 'spam and eggs'
>>> dis.dis(not_in)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               7 (not in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE    

>>> def not__in():
    not ('ham' in 'spam and eggs')
>>> dis.dis(not__in)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               7 (not in)
              9 POP_TOP             
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE        

>>> def noteq():
    not 'ham' == 'spam and eggs'
>>> dis.dis(noteq)
  2           0 LOAD_CONST               1 ('ham')
              3 LOAD_CONST               2 ('spam and eggs')
              6 COMPARE_OP               2 (==)
              9 UNARY_NOT           
             10 POP_TOP             
             11 LOAD_CONST               0 (None)
             14 RETURN_VALUE      

A princípio pensei que eles sempre davam o mesmo resultado, mas que notpor si só era simplesmente um operador de negação lógico de baixa precedência, que poderia ser aplicado a in btão facilmente quanto qualquer outra expressão booleana, ao passo que not inera um operador separado por conveniência e clareza .

A desmontagem acima foi reveladora! Parece que, embora notobviamente seja um operador de negação lógico, a forma not a in bé casada especial de forma que não está realmente usando o operador geral. Isso torna not a in bliteralmente a mesma expressão que a not in b, em vez de meramente uma expressão que resulta no mesmo valor.

Ben
fonte
4
Lembre-se de que este é apenas um detalhe de implementação. Não consigo nem encontrar uma menção de not x in xsnos documentos.
phant0m
1
@ phant0m Absolutamente; a maneira como você deve pensar not x in xsé not (x in xs). Mas o fato de que é implementado analisando-o precisamente no mesmo bytecode x not in xsmostra muito claramente que eles devem ser sempre idênticos, ao contrário de coisas como not x == yvs x != yque devem dar o mesmo resultado, mas não precisam (dependendo das implementações de __eq__e __ne__envolvidos).
Ben
11
Você se deparou com uma otimização de olho mágico de CPython ; uma otimização em tempo de compilação que outras implementações Python, como Jython e IronPython, podem ignorar ou copiar (não faz parte da especificação da linguagem).
Martijn Pieters
15

  1. Não, não há diferença.

    O operador not iné definido para ter o valor verdadeiro inverso de in.

    - documentação Python

  2. Eu diria que not iné o preferido porque é mais óbvio e eles adicionaram um caso especial para isso.

icktoofay
fonte
3

Outros já deixaram bem claro que as duas afirmações são, em um nível bastante baixo, equivalentes.

No entanto, não acho que alguém tenha enfatizado o suficiente que, uma vez que deixa a escolha para você, você deve

escolha a forma que torna seu código o mais legível possível.

E não necessariamente tão legível quanto possível para qualquer pessoa , mesmo que seja uma coisa boa de se almejar. Não, certifique-se de que o código seja o mais legível possível para você , uma vez que você é o mais propenso a voltar a este código mais tarde e tentar lê-lo.

Tomas Aschan
fonte
Se você estiver trabalhando em uma grande equipe ou em um código que provavelmente não será alterado por um tempo, é mais provável que outra pessoa precise mantê-lo.
Tommy Herbert
2

Em Python, não há diferença. E não há preferência.

Ignacio Vazquez-Abrams
fonte
1

Sintaticamente, eles são a mesma declaração. Eu seria rápido em afirmar que isso 'ham' not in 'spam and eggs'transmite uma intenção mais clara, mas já vi códigos e cenários nos quais not 'ham' in 'spam and eggs'transmitem um significado mais claro do que o outro.

Makoto
fonte