Условное выражение / троичный оператор - PullRequest
0 голосов
/ 05 сентября 2018

Я не понимаю этот синтаксис.

Программа Python для демонстрации троичного оператора

a, b = 10, 20

Используйте кортеж для выбора элемента

print( (b, a) [a < b] )

Используйте словарь для выбора элемента

print({True: a, False: b} [a < b])

PS: Полагаю, это из более старой версии Python, потому что в более новых версиях (не знаю, из какой версии) True и False являются зарезервированными ключевыми словами, поэтому им нельзя присвоить значение.

лямда более эффективна, чем указанные выше два метода потому что в лямбде мы уверены, что только одно выражение будет оцениваться в отличие от кортеж и словарь

print((lambda: b, lambda: a)[a < b]())

Синтаксис должен быть:

[on_true] if [выражение] else [on_false]

Так как же

print( (b, a) [a < b] )
print({True: a, False: b} [a < b])
print((lambda: b, lambda: a)[a < b]())

соответствует этому синтаксису? Что означает [a<b] после кортежа / словаря / лямбды? Я никогда не видел этот синтаксис раньше. Это также работает, когда список [b, a] предшествует [a<b].

Я бы ожидал, что это будет выглядеть так

print( a if a < b else b )

Ссылка на ресурс: https://www.geeksforgeeks.org/ternary-operator-in-python/

Ответы [ 3 ]

0 голосов
/ 05 сентября 2018

Первое замечание, что все они дают минимум значение a и b:

a, b = 10, 20

res1 = (b, a)[a < b]                    # 10
res2 = {True: a, False: b}[a < b]       # 10
res3 = (lambda: b, lambda: a)[a < b]()  # 10

Мы можем рассмотреть их по очереди:

  1. res1 создает tuple из 2 целых чисел. a < b возвращает логическое значение, в данном случае True. В Python True == 1, поскольку bool является подклассом int. Наконец, [] является синтаксическим сахаром для __getitem__, который является методом, вызываемым для позиционной индексации. Поскольку Python начинает считать с 0, первый индекс - a. Вы также можете подтвердить это самостоятельно: (b, a).__getitem__(1) возвращает 10.
  2. res2 создает словарь, отображающий логические значения в a & b. Вызов __getitem__ объекта dict возвращает значение для данного ключа. Здесь ключ, как и прежде, True. Поскольку словарь отображает True на a, это возвращаемое значение.
  3. res3 создает набор анонимных (lambda) функций, каждая из которых возвращает скаляры, а именно b и a. Согласно res1, элемент может быть извлечен из кортежа посредством целочисленной индексации. Единственным дополнительным требованием является фактический вызов функций lambda через ().

Обратите внимание, что ни один из них не работает так же, как троичный оператор , который применяется во время компиляции (см. Комментарии) через встроенный if / else:

res4 = a if a < b else b
0 голосов
/ 05 сентября 2018

Ваше заблуждение может быть связано с Во всех этих случаях логический результат оценки В случае

print( (b, a) [a < b] )

и

print((lambda: b, lambda: a)[a < b]())

объект - это кортеж, содержащий либо сами переменные, либо очень простые анонимные функции, которые возвращают эти переменные.

В случае

print({True: a, False: b} [a < b])

выражение вычисляется и используется в качестве ключа для словаря, который имеет как True, так и False в качестве ключей. Предположение, что это означает, что это должна быть более старая версия Python, неверно, поскольку словарь не представляет переназначение значений, а представляет собой просто структуру данных, в которой ключ отображается на значение. True и False являются действительными ключами, и именно это обстоятельство и используется здесь.

Наконец:

 print( a if a < b else b )

Это хороший и лаконичный способ выразить то же самое и фактически строку кода, которую я использовал бы в этом случае

0 голосов
/ 05 сентября 2018

a<b - это bool (True или False). Поскольку bool является подтипом int, его можно использовать в контексте, где ожидается целое число, например как индекс списка / кортежа:

>>> True == 1
True
>>> False == 0
True
>>> isinstance(True, int)
True
>>> ('a', 'b')[True]  # True == 1
'b'
>>> ('a', 'b')[1<2]  # 1<2 == True == 1
'b'
>>> ('a', 'b')[2<1]  # 2<1 == False == 0
'a'

Для dict ключей это похоже, но приведение типов даже не требуется:

>>> {True: 'a', False: 'b'}[1<2]  # 1<2 == True
'a'
...