Я понимаю, что он делает, но почему python делает это - т. е. Возвращает значение, а не True / False?
10and7-2
возвращает 5. Аналогично, изменение "и" на "или" приведет к изменению функциональности. Итак
10or7 - 2
Вернет 10.
Это законный / надежный стиль, или есть какие-то подводные камни по этому поводу?
Переведено автоматически
Ответ 1
TL; DR
Мы начнем с обобщения поведения двух логических операторов and и or. Эти идиомы лягут в основу нашего обсуждения ниже.
and
Возвращает первое ложное значение, если таковое имеется, в противном случае возвращает последнее значение в выражении.
or
Возвращает первое истинное значение, если таковое имеется, в противном случае возвращает последнее значение в выражении.
Поведение также кратко описано в документации, особенно в этой таблице:
Операция
Результат
x or y
если x равно false, то y, иначе x
x and y
если x равно false, то x, иначе y
not x
если x равно false, то True, else False
Единственный оператор, возвращающий логическое значение независимо от его операндов, - это not operator .
Оценки "правдивости" и "Правдивости"
Инструкция
len(args) andmax(args) - min(args)
Это оченьпитоновский лаконичный (и, возможно, менее читаемый) способ сказать "если args не пустое, верните результат max(args) - min(args)", в противном случае верните 0. В общем, это более краткое представление if-else выражения. Например,
exp1 and exp2
Следует (примерно) перевести на:
r1 = exp1 if r1: r1 = exp2
Или, что эквивалентно,
r1 = exp2 if exp1 else exp1
Аналогично,
exp1 or exp2
Should (roughly) translate to:
r1 = exp1 ifnot r1: r1 = exp2
Or, equivalently,
r1 = exp1 if exp1 else exp2
Where exp1 and exp2 are arbitrary python objects, or expressions that return some object. The key to understanding the uses of the logical and and or operators here is understanding that they are not restricted to operating on, or returning boolean values. Any object with a truthiness value can be tested here. This includes int, str, list, dict, tuple, set, NoneType, and user defined objects. Short circuiting rules still apply as well.
But what is truthiness?
It refers to how objects are evaluated when used in conditional expressions. @Patrick Haugh summarises truthiness nicely in this post.
All values are considered "truthy" except for the following, which are "falsy":
None
False
0
0.0
0j
Decimal(0)
Fraction(0, 1)
[] - an empty list
{} - an empty dict
() - an empty tuple
'' - an empty str
b'' - an empty bytes
set() - an empty set
an empty range, like range(0)
objects for which
obj.__bool__() returns False
obj.__len__() returns 0
A "truthy" value will satisfy the check performed by if or while statements. We use "truthy" and "falsy" to differentiate from the bool values True and False.
How and Works
We build on OP's question as a segue into a discussion on how these operators in these instances.
Given a function with the definition
deffoo(*args): ...
How do I return the difference between the minimum and maximum value in a list of zero or more arguments?
Найти минимум и максимум несложно (используйте встроенные функции!). Единственная загвоздка здесь заключается в правильной обработке углового случая, когда список аргументов может быть пустым (например, вызов foo()). Мы можем выполнить и то, и другое в одной строке благодаря оператору and:
Поскольку используется and, второе выражение также должно быть вычислено, если используется первое True. Обратите внимание, что, если первое выражение оценивается как истинное, возвращаемое значение всегда является результатом второго выражения. Если первое выражение оценивается как ложное, то возвращаемый результат является результатом первого выражения.
В приведенной выше функции, если foo получает один или несколько аргументов, то len(args) больше 0 (положительное число), поэтому возвращаемый результат равен max(args) - min(args). OTOH, если аргументы не переданы, len(args) is 0, который является ложным, и 0 возвращается.
Обратите внимание, что альтернативным способом написания этой функции было бы:
Конечно, ни одна из этих функций не выполняет никакой проверки типов, поэтому, если вы полностью не доверяете предоставленным входным данным, не полагайтесь на простоту этих конструкций.
Как or работает
Я объясняю работу or аналогичным образом на надуманном примере.
Дана функция с определением
deffoo(*args): ...
Как бы вы завершили, foo чтобы вернуть все числа заново 9000?
Мы используем or для обработки углового регистра здесь. Мы определяем foo как:
deffoo(*args): return [x for x in args if x > 9000] or'No number over 9000!'
foo(9004, 1, 2, 500) # [9004]
foo(1, 2, 3, 4) # 'No number over 9000!'
foo выполняет фильтрацию в списке, чтобы сохранить все числа над 9000. Если такие числа существуют, результатом понимания списка является непустой список, который соответствует действительности, поэтому он возвращается (здесь происходит короткое замыкание в действии). Если таких чисел не существует, то результатом составления списка будет [] что неверно. Итак, теперь вычисляется второе выражение (непустая строка) и возвращается.
Используя условные выражения, мы могли бы переписать эту функцию как,
deffoo(*args): r = [x for x in args if x > 9000] ifnot r: return'No number over 9000!'
return r
Как и прежде, эта структура более гибкая с точки зрения обработки ошибок.
Обратите внимание, что ни and, ни orнеограничиваютзначение и тип, которые они возвращают False иTrue, а скорее возвращают последний вычисленный аргумент, к которому они возвращаются.. Иногда это полезно, например, если s это строка, которую следует заменить значением по умолчанию, если оно пустое, выражение s or 'foo' выдает желаемое значение.
Итак, вот как Python был разработан для вычисления булевых выражений, и приведенная выше документация дает нам представление о том, почему они сделали это именно так.
Чтобы получить логическое значение, просто введите его.
returnbool(len(args) andmax(args)-min(args))
Почему?
Короткое замыкание.
Например:
2and3# Returns 3 because 2 is Truthy so it has to check 3 too 0and3# Returns 0 because 0 is Falsey and there's no need to check 3 at all
То же самое относится и к or too , то есть оно вернет правдивое выражение, как только найдет его, потому что вычисление остальной части выражения избыточно.
Вместо того, чтобы возвращать жесткое True или False, Python возвращает Truthy или Falsey, которые в любом случае будут оцениваться в True или False. Вы могли бы использовать выражение как есть, и оно все равно будет работать.
Чтобы узнать, что является правдивым, а что ложным, ознакомьтесь с ответом Патрика Хо
Ответ 3
и и или выполняют логическую логику, но при сравнении возвращают одно из фактических значений. При использовании и значения вычисляются в логическом контексте слева направо. 0, ", [], (), {}, и None являются false в логическом контексте; все остальное равно true.
Если все значения истинны в логическом контексте, и возвращает последнее значение.
>>> 2and5 5 >>> 2and5and10 10
Если какое-либо значение равно false в логическом контексте и возвращает первое значение false.
>>> ''and5 '' >>> 2and0and5 0
Итак, код
returnlen(args) andmax(args)-min(args)
возвращает значение max(args)-min(args) при наличии аргументов, иначе оно возвращает len(args) значение 0.
Ответ 4
Это законный / надежный стиль, или есть какие-то подводные камни по этому поводу?
Вы приводите хороший пример. Функция вернет 0, если аргументы не переданы, и коду не нужно проверять наличие особого случая отсутствия переданных аргументов.
Другой способ использовать это - использовать аргументы None по умолчанию для изменяемого примитива, например, для пустого списка:
deffn(alist=None): alist = alist or [] ....
If some non-truthy value is passed to alist it defaults to an empty list, handy way to avoid an if statement and the mutable default argument pitfall