«Булевы» операции в Python (т.е. операторы and и / или) - PullRequest
10 голосов
/ 30 сентября 2010

Этот метод ищет первую группу символов слова (т.е.: [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 равно false, возвращается его значение;в противном случае y вычисляется и возвращается полученное значение.

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

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

Ответы [ 5 ]

6 голосов
/ 30 сентября 2010

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

Краткость (и, следовательно, ясность, как только вы к этому привыкнете, поскольку в конце концов это не жертвовать читабельностью вообще! -) каждый раз, когда вам нужно что-то проверить и использовать это что-то, если оно истинно, или другое значение, если это что-то ложно (это для and - отменить это для or - и я 'm очень сознательно избегая фактических ключевых слов или аналогичных True и False, поскольку я говорю о каждом объекте, а не только bool! -).

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

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 самым популярным диалектом Pascal всех времен, было именно то, что Turbo реализовал and и or так же, как Python позже (и язык Cделал раньше ...).

4 голосов
/ 30 сентября 2010

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

Нет.

в чем смысл этой довольно неинтуитивной реализации?

"не интуитивно"?В самом деле?Я бы не согласился.

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

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

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

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

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

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

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


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

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

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

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

0 голосов
/ 26 ноября 2014

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

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

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

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

Почти в каждом общем языке '&' или '&&' или 'AND' является логической или булевой функцией.За кулисами оптимизирующие компиляторы могут использовать краткую логику, подобную описанной выше, в LOGIC FLOW, но не модификацию СТРУКТУРЫ ДАННЫХ (любой оптимизирующий компилятор, который изменил значение таким образом, считался бы неработающим), но если значение предполагается использовать в переменнойдля дальнейшей обработки он должен быть логического или логического типа, поскольку в большинстве случаев это «формально» для этих операторов.

0 голосов
/ 30 сентября 2010

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

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

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

Это очень распространенная и очень базовая оптимизация, которую делают многие языки.

0 голосов
/ 30 сентября 2010

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

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

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

Может быть, это обратное обоснование; Я не уверен, но в любом случае логические операторы 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().

...