Можете ли вы упростить цепочечные сравнения с не равными или равными в Python? [Дубликат]

1

Вероятно, некоторые из вас могут подумать, что это дубликат, и да, я нашел много примеров, подобных этому: Изображение 174551

Но Pycharm говорит, что я могу просто это:

if y > x and x != -1:
    #  do something

И я искал и не мог найти что-то подобное. Мой вопрос: правильно ли упростить эту функцию следующим образом:

if y > x != -1:
    #  do something

И если это так, безопасно ли и существует ли какая-либо разница между этой версией и не упрощенной версией, за исключением того, что она короче? Если это не правильный способ его упростить, то что тогда?

  • 4
    это эквивалентно, но не самое читаемое ...
  • 2
    Согласился с @Jean-FrançoisFabre. Жан-Франсуа Фабр. Это может быть короче, но удобство чтения - одна из приятных вещей в Python, и, кажется, стыдно выбрасывать его, чтобы сохранить несколько символов. Особенно, если кто-то может закончить работу с вашим кодом и перефразировать ваши собственные опасения по поводу его безопасности и правильности.
Показать ещё 2 комментария
Теги:

1 ответ

3
Лучший ответ

это функционально эквивалентно, но когда это:

10 < x < 40

приятно читать, смешивая разных операторов, чтобы использовать скованные сравнения, не лучший выбор.

Это действительно то же самое? позвольте разобраться, чтобы узнать:

def f1(x,y):
    if y > x and x != -1:
        return 0

def f2(x,y):
    if y > x != -1:
        return 0

import dis

print("function 1")
dis.dis(f1)
print("function 2")
dis.dis(f2)

результат:

function 1
  2           0 LOAD_FAST                1 (y)
              3 LOAD_FAST                0 (x)
              6 COMPARE_OP               4 (>)
              9 POP_JUMP_IF_FALSE       28
             12 LOAD_FAST                0 (x)
             15 LOAD_CONST               3 (-1)
             18 COMPARE_OP               3 (!=)
             21 POP_JUMP_IF_FALSE       28

  3          24 LOAD_CONST               2 (0)
             27 RETURN_VALUE
        >>   28 LOAD_CONST               0 (None)
             31 RETURN_VALUE
function 2
  6           0 LOAD_FAST                1 (y)
              3 LOAD_FAST                0 (x)
              6 DUP_TOP
              7 ROT_THREE
              8 COMPARE_OP               4 (>)
             11 JUMP_IF_FALSE_OR_POP    23
             14 LOAD_CONST               3 (-1)
             17 COMPARE_OP               3 (!=)
             20 JUMP_FORWARD             2 (to 25)
        >>   23 ROT_TWO
             24 POP_TOP
        >>   25 POP_JUMP_IF_FALSE       32

  7          28 LOAD_CONST               2 (0)
             31 RETURN_VALUE
        >>   32 LOAD_CONST               0 (None)
             35 RETURN_VALUE
>>> 

Удивительно, но они не то же самое, и у прикованной версии есть больше инструкций.

Не уверен, что происходит здесь (некоторые заняли больше времени, чтобы объяснить это лучше: как скопированные сравнения в Python на самом деле работают?), Но на самом деле я придерживаюсь and версии, ярлыки и настолько читаемые (подумайте о будущих помощниках тоже...).

Тем не менее, одна интересная вещь о цепных сравнениях будет заключаться в том, что если центральный аргумент вычисляется/занимает много времени, чтобы вычислить/имеет побочный эффект в вычислении, и вы не хотите его хранить в переменной:

if y > super_long_computation(x) != -1:

В этом случае центральный аргумент оценивается только один раз. В случае and, вам придется хранить его заранее.

  • 1
    Байт-код делает эквивалентные вещи, но перепрыгивает через некоторые обручи, чтобы вычислять только один раз x , что может быть выражением типа x**2 , которое он будет вычислять только один раз
  • 0
    Вот хорошая разбивка
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню