Лутц М. - Изучаем Python (1077325), страница 70
Текст из файла (страница 70)
пот Х Истина, значение Х ложно (выражение возвращает значение Тгсе или Еа1ве) Здесь Х и У могут быть любыми значениями истинности или выражениями, которые возвращают значения истинности (например, выражение проверки равенства, сравнение с диапазоном значений и т. д.). В языке Рус]гоп логические операторы имеют вид слов (вместо обозначений И, ~ ~ и!, как это реализовано в языке С).
Кроме того, логические операторы вп() и ог возвращают истинный или ложный объект, а не значение Тгце или Ев1ве. Рассмотрим несколько примеров, чтобы понять, как они работают: »> 2 < 3, 3 < 2 (Тгое, Ев1ее) Ф Меньше чеи; возврашвет 7 или О Операция сравнения величин, как в данном случае, возвращает в качестве результата значение Тгсе или Еа1ве, которые, как мы узнали в главах б и 9, в действительности являются особыми версиями целых чисел 1 и О (выводятся они особым образом, а во всем остальном являются обычными числами). С другой стороны, операторы впз и от всегда возвращают объект — объект либо слева от оператора, либо справа.
Если действие этих операторов проверяется инструкцией (г или другими инструкциями, они будут иметь ожидаемый результат (не забывайте, что каждый объект может интерпретироваться как истина или как ложь), но это не будут простые значения Тгое или Еа1ве. В случае оператора ог интерпретатор начинает вычислять значения объектов-операндов слева направо и возвращает первый, имеющий истинное значение.
Кроме того, интерпретатор прекратит дальнейшие вычисления, как только будет найден первый объект, имеющий истинное значение. Это обычно называют вычислением ло короткой схеме, так как конечный результат становится известен еще до вычисления остальной части выражения: Ф Вернет левый операнд, если он ииеет истинное значение в Мнвче вернет правый операнд (истинный или поиный) »>2огЗ, Зог2 (2, 3) »> ( ] ог 3 3 »> ( ] аг ( ) ( ) В первой строке предыдущего примера оба операнда (2 и 3) имеют истинные (т. е. ненулевые) значения, поэтому интерпретатор всегда бу- Проверка истинности дет останавливать вычисления и возвращать операнд слева. В других двух операциях левый операнд имеет ложное значение (пустой объект), поэтому интерпретатор просто вычисляет и возвращает объект справа (который может иметь как истинное, так и ложное значение).
Вычисление оператора апб также останавливается, как только результат станет известен, однако в этом случае интерпретатор вычисляет операнды слева направо и возвращает первый объект, имеющий лозгное значение: »> 2 апб 3, 3 апб 2 В Вернет .левый операнд, если он ииеет ложное значение (3, 2) в Иначе вернет правый операнд (иотинный или ложный) »> [ 1 апб ( ) [ 1 »> 3 апб [ 1 [ 1 Здесь в первой строке оба операнда имеют истинные значения, поэтому интерпретатор вычислит оба операнда и вернет объект справа.
Во второй проверке левый операнд имеет ложное значение ([)), поэтому интерпретатор останавливает вычисления и возвращает его в качестве результата проверки. В последней проверке левый операнд имеет истинное значение (3), поэтому интерпретатор вычисляет и возвращает объект справа (который имеет ложное значение [ ]). Конечный результат будет тот же, что и в языке С и во многих других языках, — вы получаете значение, которое логически интерпретируется как истина или ложь при использовании в инструкции 1Г или ип[1е. Однако в языке РуФЬоп логические операторы возвращают либо левый, либо правый объект, а не простое целочисленное значение.
Такое поведение операторов впб и ог может показаться странным на первый взгляд, поэтому загляните во врезку «Придется держать в уме: логические значения», где вы найдете примеры, как иногда эта особенность может использоваться программистами на языке РуФЬоп.
Трехместное выражение Ы/е! бе Одна из основных ролей логических операторов в языке РуФЬоп заключается в образовании выражений, которые выполняются так же, как условная инструкция тт. Рассмотрим следующую инструкцию, которая записывает в А значение У или 2 в зависимости от истинности значения Х: )Г Х: А=У е1ве. А = 7 Иногда, как в данном примере, элементы инструкции настолько просты, что кажется излишеством тратить на них четыре строки. В некоторых случаях у нас может появиться желание вложить такую конст- Глава)7.
Условная инструкция б рукцию внутрь другой инструкции вместо того, чтобы выполнять присваивание переменной. По этим причинам (и, откровенно говоря, потому что в языке С имеется похожая возможность>) в версии РуФЬоп 2.5 появилась новая конструкция, позволяющая записать те же действия в виде единственного выражения: А = У >Г Х е1зе 7 Данное выражение дает тот же результат, что и предыдущая инструкция 1Г, но выглядит она проще. Как и в предыдущей инструкции, интерпретатор выполняет выражение У, только если проверка ! Г Х дает истинное значение, а выражение 7 выполняется, только если проверка 1( Х дает ложное значение.
То есть вычисления здесь также выполняются по сокращенной схеме. Ниже приводятся несколько примеров выражения в действии: »> А = 'т' !Г 'враз' в1ве 'т' г неоустая строка - это истяна »> А »> А = 'С' !Г '' а1ве 'Г >» А До версии РуФЬоп 2.5 (да и после) тот же эффект можно было получить за счет комбинирования операторов ало и от благодаря тому, что они возвращают объект слева или справа: А = ((Х аоа у) от 7) Этот прием работает, но он скрывает в себе ловушку — он предполагает, что У будет иметь истинное значение. В этом случае эффект будет тот же самый: оператор алб выполнится первым и вернет У, если Х имеет истинное значение.
В противном случае оператор от просто вернет 7. Другими словами, мы получаем: «11 Х ФЬеп У е1ве 2». Эта комбинация операторов ало/от требует некоторого времени, чтобы осознать ее при первом знакомстве, но, начиная с версии 2.5, надобность в таком приеме отпала, так как существует более наглядная кон- струкция У !Г Х е1ве 7, которуюможноиспользоватьвкачествевыражения. Если же составляющие достаточно сложны, лучше использовать полноценную инструкцию 1(.
В качестве дополнительного примечания: в языке РуФЬоп следующее выражение дает похожий эффект — благодаря тому, что функция Ьоо1 В действительности, порядок следования операндов в выражении Х !Г У е1за 7 в языке РУ1Ьоп несколькоотличается отвыраженияу ? Х: 7 вязыке С. Такой порядок был выбран в соответствии с анализом наиболее распространенных шаблонов программирования в языке Руьйоп, а также отчасти, чтобы помочь бывшим программистам на языке С избавиться от привычки злоупотреблять этим выражением. Не забывайте, что в языке Ру!)>оп исповедуется принцип — чем проще, тем лучше.
327 Проверка истинности преобразует Х в соответствующее целое число 1 или О, которое затем используется для выбора требуемого значения из списка: А = [2, тйвоо((Х)) Придется держать в уме: логические значения В языке Ру$)топ часто используется прием выбора одного объекта из множества, основанный на необычном поведении логических операторов. Следующая инструкция: Х = А ог В ог С ог попе присвоит переменной Х первый непустой (имеющий истинное значение) объект из множества объектов А, В и С или Мопе, если все эти объекты окажутся пустыми.
Этот прием стал возможен благодаря тому, что оператор ог возвращает один из двух объектов и, как оказывается, это весьма распространенная парадигма программирования на языке РуФ)топ1 чтобы выбрать непустой объект из фиксированного множества, достаточно просто объединить их в выражение с помощью оператора о г. Также важно осознать, как выполняются вычисления по сокращенной схеме, потому что справа от логического оператора может находиться функция, выполняющая важную работу илн оказывающая побочное влияние, вызов которой не произойдет из-за действия правила вычисления по сокращенной схеме: тт (1() Ег Гг(): В данном случае, если функция г1 вернет истинное (или непустое) значение, интерпретатор никогда не вызовет функцию (2.
Чтобы гарантировать вызов обеих функций, можно вызвать их до применения оператора от: тэр1, тэр2 = Г1(), (2() (Г терт Ог тар2: Вы уже видели другой вариант использования такого поведения: благодаря особенностям работы логических операторов выражение ((А апо' В) ог С) может использоваться для имитации инструкции т(/е1ве. Кроме того, обратите внимание: вследствие того, что все объекты могут расцениваться как истинные или ложные значения, в языке РуФ[топ легко и просто выполнить проверку объекта напрямую ((( Х:) вместо того, чтобы сравнивать его с пустым значением (1( Х ! = ' '; ).
В случае строк эти две проверки равнозначны. згв Глава 12. Условная инструкция И Например: »> 1 Г, с Кьоон")] »> Гт', 'С'Паоо1гвааа')) 'т' Однако это далеко не то же самое, потому что в данном случае интерпретатор не использует сокращенную схему вычисления — он всегда будет вычислять оба значения 2 и У независимо от значения Х.
Из-за всех этих сложностей лучше использовать более простое и более понятное выражение 1Г/е1ве, появившееся в версии РуФЬоп 2.5. Кроме того, этим выражением не следует злоупотреблять и следует использовать его, только если части выражения достаточно просты, в противном случае лучше использовать обычную инструкцию 1Г, что облегчит модификацию программного кода в будущем.