"Логические" операции в 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" должна возвращать целое число, а не строку.
в строке такие функции, как основные артритные и логические функции (+ -|*/&!) являются еще более сдержанными, потому что за ними также стоит история формальной математической теории. (Подумайте обо всех аргументах о порядке операций для этих функций)
чтобы фундаментальные функции возвращали что-либо, кроме их наиболее распространенного типа данных (логического или числового), следует классифицировать как целенаправленное запутывание.
в почти каждом общем языке " & " или "& & " или " и " является логикой или Булева функция. За кулисами компиляторы оптимизации могут использовать короткую логику резания, как указано выше, в логическом потоке, но не модификацию структуры данных (любой оптимизирующий компилятор, который изменил значение таким образом, считался бы сломанным), но если ожидается, что значение будет использоваться в переменной для дальнейшей обработки, оно должно быть в логическом или булевом типе, потому что это "формальное" для этих операторов в большинстве случаев.