Ответ 1
Две формы делают одинаковый байт-код, как вы можете четко проверить:
>>> import dis
>>> dis.dis(compile('if x not in d: pass', '', 'exec'))
1 0 LOAD_NAME 0 (x)
3 LOAD_NAME 1 (d)
6 COMPARE_OP 7 (not in)
9 JUMP_IF_FALSE 4 (to 16)
12 POP_TOP
13 JUMP_FORWARD 1 (to 17)
>> 16 POP_TOP
>> 17 LOAD_CONST 0 (None)
20 RETURN_VALUE
>>> dis.dis(compile('if not x in d: pass', '', 'exec'))
1 0 LOAD_NAME 0 (x)
3 LOAD_NAME 1 (d)
6 COMPARE_OP 7 (not in)
9 JUMP_IF_FALSE 4 (to 16)
12 POP_TOP
13 JUMP_FORWARD 1 (to 17)
>> 16 POP_TOP
>> 17 LOAD_CONST 0 (None)
20 RETURN_VALUE
поэтому, очевидно, они семантически идентичны.
В стиле PEP 8 не упоминается проблема.
Лично я предпочитаю форму if x not in y
, которая сразу же очищает, что not in
- это один оператор, и "читается как английский". if not x in y
может ввести некоторых читателей в заблуждение, думая, что это означает if (not x) in y
, читает немного меньше, чем английский, и не имеет абсолютно никаких компенсационных преимуществ.