"Булевы" операции в Python (т.е. операторы and и / или)
Этот метод ищет первую группу символов слова (то есть: [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
оценивается, и полученное значение возвращается.
Тем не менее, будучи логическим оператором (в руководстве даже сказано так), я ожидал and
вернуть логическое значение. В результате я был удивлен, когда узнал (как) это работает.
Каковы другие варианты использования этого и / или каково обоснование для этой довольно неинтуитивной реализации?
5 ответов
Каковы другие варианты использования этого,
Краткость (и, следовательно, ясность, как только вы к этому привыкнете, поскольку, в конце концов, это совсем не жертвует читабельностью!-), в любое время вам нужно что-то проверять и либо использовать это что-то, если это правда, либо другое значение, если это что-то ложно (это для and
- поменять его на or
- и я очень сознательно избегаю реальных ключевых слов или тому подобное 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 сделал раньше...).
Каковы другие варианты использования этого,
Нет.
В чем смысл этой довольно не интуитивной реализации?
"Неинтуитивный"? В самом деле? Я бы не согласился.
Давай подумаем.
"А и В " фальсифицируется, если a
ложно Таким образом, первое ложное значение достаточно, чтобы знать ответ. Зачем беспокоиться о трансформации a
к другому логическому? Это уже ложно. Насколько больше ложных False
? В равной степени неверно, верно?
Так a
значение - когда эквивалентно False
- достаточно ложно, так что это значение всего выражения. Никакой дальнейшей конверсии или обработки. Готово.
когда a
значение эквивалентно True
затем b
это все, что требуется. Никакой дальнейшей конверсии или обработки. Зачем преобразовывать b
к другому логическому? Это ценность - это все, что нам нужно знать. Если это что-то вроде True
тогда это достаточно верно. Насколько вернее True
?
Зачем создавать ложные дополнительные объекты?
Тот же анализ для или.
Зачем преобразовывать в логическое значение? Это уже достаточно верно или достаточно ложно. Насколько больше True это может получить?
Попробуй это.
>>> False and 0
False
>>> True and 0
0
>>> (True and 0) == False
True
В то время как (True and 0)
на самом деле 0
это равно False
, Этого достаточно для всех практических целей.
Если это проблема, то bool(a and b)
заставит явное преобразование.
Я думаю, что хотя эта запись "работает", она представляет собой плохой стиль кодирования, который скрывает логику и сбивает с толку более опытных программистов, у которых будет "багаж" знаний о том, как работает большинство других языков.
В большинстве языков возвращаемое значение активной функции определяется типом функции. Если это не было явно перегружено. Пример Ожидается, что функция типа 'strlen' будет возвращать целое число, а не строку.
В линейных функциях, таких как основные артритические и логические функции (+-/*|&!), Еще более ограничены, потому что они также имеют историю формальной математической теории. (Подумайте обо всех аргументах о порядке операций для этих функций)
Чтобы фундаментальные функции возвращали что-либо, кроме их наиболее распространенного типа данных (логического или числового), их следует классифицировать как целенаправленное запутывание.
Почти в каждом общем языке '&' или '&&' или 'AND' является логической или логической функцией. За кулисами, компиляторы оптимизации могут использовать краткую логику, как описано выше в LOGIC FLOW, но не модификацию СТРУКТУРЫ ДАННЫХ (любой оптимизирующий компилятор, который изменил значение таким образом, считался бы неработающим), но если значение предполагается использовать в переменной для дальнейшей обработки он должен иметь логический или логический тип, поскольку в большинстве случаев это "формально" для этих операторов.
В принципе a and b
возвращает операнд, который имеет то же значение истинности, что и все выражение.
Это может показаться немного запутанным, но просто сделайте это в своей голове: Если a
является False
, затем b
больше не имеет значения (потому что False and anything
всегда будет False
), чтобы он мог вернуться a
сразу.
Но когда a
является True
только тогда b
имеет значение, так что возвращается b
сразу, даже не глядя.
Это очень распространенная и очень базовая оптимизация, которую делают многие языки.
Я не нахожу это удивительным, и фактически ожидал, что это сработает, когда я первоначально попробовал это.
Хотя не все значения bools
Обратите внимание, что в действительности все значения являются логическими - они представляют собой истинное значение. (В Python bool
в действительности - это значение, которое представляет только истину или ложь.) Число 0
не bool, но он явно (в 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()
,