"Логические" операции в Python (т. е. операторы and/or)

этот метод ищет первую группу символов слова (т. е.:[a-zA-Z0-9_]), возвращая первую совпадающую группу или None в случае неудачи.

def test(str):
    m = re.search(r'(w+)', str)
    if m:
        return m.group(1)
    return None

та же функция может быть переписана следующим образом:

def test2(str):
    m = re.search(r'(w+)', str)
    return m and m.group(1)

это работает так же, и описанное поведение; как на этой странице четко указано:

выражение x and y сначала оценивает x; если x ложно, то его значение возвращается; в противном случае y is вычисляется и полученное значение возвращается.

однако, будучи логическим оператором (он даже говорит об этом в руководстве), я ожидал and для возврата логического значения. В результате я был удивленные когда я узнал (как) это работает.

каковы другие варианты использования этого и / или каково обоснование этой довольно неинтуитивной реализации?

5 ответов


каковы другие варианты использования этого

лаконичность (а значит ясность, как только к ней привыкнешь, так как все-таки она делает не пожертвовать читабельностью вообще!- ) в любое время вам нужно что-то проверить и либо использовать это что-то, если это правда, либо другое значение, если это что-то ложно (это для and -- reverse it for or - и я очень умышленно избегая реального запросам-или-как True и False, Я говорю о каждый объект, а не просто bool!-).

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

inverses = [x and 1.0/x for x in values]

в шесть, таких как:

inverses = []
for x in values:
    if x:
        inverses.append(1.0/x)
    else:
        inverses.append(x)

или более тесные версии.

и / или каково обоснование этого довольно сложным в реализации?

отнюдь не будучи "неинтуитивными", новички регулярно спотыкались о то, что некоторые языки (например, стандартный Паскаль) делали не укажите порядок оценки и характер короткого замыкания and и or; одно из различий между Turbo Pascal и языковым стандартом, который в свое время сделал Turbo самым популярным диалектом Паскаля раз, было именно то, что Turbo реализовано and и or так же, как Python сделал позже (и язык C сделал раньше...).


каковы другие варианты использования этого

нет.

каково обоснование этой довольно неинтуитивной реализации?

"нелогично"? Неужели? Я бы не согласился.

давайте подумаем.

" a и b " фальсифицируется, если a является false. Поэтому первого ложного значения достаточно, чтобы знать ответ. Зачем беспокоиться о преобразовании a на другой логический? Это уже ложный. Насколько больше ложь False? Тоже ложь, верно?

так a ' s значение -- когда эквивалентно False -- достаточно ложно, так что это значение всего выражения. Нет дальнейшего преобразования или обработки. Сделанный.

, когда a ' s значение эквивалентно True затем - это все, что требуется. Нет дальнейшего преобразования или обработки. Зачем трансформировать b на другой логический? Это все, что нам нужно знать. Если это что-то как True, то это правда. Насколько вернее True?

зачем создавать ложные дополнительные объекты?

тот же анализ для или.

почему преобразование в Boolean? Это уже достаточно верно или достаточно ложно. Насколько правдивее это может быть?


Попробуйте Это.

>>> False and 0
False
>>> True and 0
0
>>> (True and 0) == False
True

пока (True and 0) на самом деле 0, равен False. Это ложь-достаточно для всех практических цели.

если это проблема, то bool(a and b) принудит явное преобразование.


Я не нашел это удивительным, и на самом деле ожидал, что это сработает, когда я изначально попробовал.

пока не все значения bools, обратите внимание, что в действительности все значения boolean--они представляют ценность истины. (В Python, a bool и--в результате--значение, которое только представляет true или false.) Число 0 не является bool, но он явно (в Python) имеет логическое значение False.

другими словами, логический оператор and не всегда возвращает bool, но это всегда возвращает логическое значение; тот, который представляет true или false, даже если он также имеет другую информацию, логически присоединенную к нему (например. строка.)

возможно, это ретроактивное оправдание; я не уверен, но в любом случае кажется естественным, что булевы операторы Python ведут себя так, как они.


когда его использовать?

в вашем примере test2 чувствует себя яснее для меня. Я могу сказать, что они оба делают одинаково: конструкция в test2 не делает ее более трудной для понимания. Все остальное равно, более сжатый код в test2-незначительно-быстрее понимается. Тем не менее, это тривиальная разница, и я не хочу, чтобы я переписывал что-либо.

это может быть также полезно и другими способами:

a = {
    "b": a and a.val,
    "c": b and b.val2,
    "d": c and c.val3,
}

это может быть переписано по-другому, но это ясно, просто и лаконично.

Не выходите за борт; " a () и b () или c ()" в качестве замены "a ()? b (): c ()" опасно и запутанно, так как вы закончите с c (), если B () ложно. Если вы пишете терниарное утверждение, используйте терниарный синтаксис, даже если он ужасно уродлив:b() if a() else c().


в принципе a and b возвращает операнд, который имеет то же значение истинности, что и все выражение.

это может показаться немного запутанным, но просто сделайте это в своей голове: если a is False, потом b больше не имеет значения (потому что False and anything всегда будет False), поэтому он может вернуться a сразу.

но когда a is True затем только b имеет значение, поэтому он возвращается b сразу, даже не глядя.

это очень общая и очень базовая оптимизация на многих языках.


Я думаю, что, хотя эта нотация "работает", она представляет собой плохой стиль кодирования, который скрывает логику и запутает более опытных программистов, у которых будет "багаж" знаний о том, как работает большинство других языков.

в большинстве языков возвращаемое значение активной функции определяется типом функции. Если только он явно не перегружен. Пример функция типа "strlen" должна возвращать целое число, а не строку.

в строке такие функции, как основные артритные и логические функции (+ -|*/&!) являются еще более сдержанными, потому что за ними также стоит история формальной математической теории. (Подумайте обо всех аргументах о порядке операций для этих функций)

чтобы фундаментальные функции возвращали что-либо, кроме их наиболее распространенного типа данных (логического или числового), следует классифицировать как целенаправленное запутывание.

в почти каждом общем языке " & " или "& & " или " и " является логикой или Булева функция. За кулисами компиляторы оптимизации могут использовать короткую логику резания, как указано выше, в логическом потоке, но не модификацию структуры данных (любой оптимизирующий компилятор, который изменил значение таким образом, считался бы сломанным), но если ожидается, что значение будет использоваться в переменной для дальнейшей обработки, оно должно быть в логическом или булевом типе, потому что это "формальное" для этих операторов в большинстве случаев.