([False, True] и [True, True]) вычисляется как [True, True]

#python #python-3.x #boolean

#python #python-3.x #логическое

Вопрос:

Я наблюдал следующее поведение в python 3:

 >>> ([False, True] and [True, True])
[True, True]

>>> ([False, True] or [True, True])
[False, True]
  

Я ожидал с точностью до наоборот:

 [False, True] and [True, True] = [False and True, True and True] = [False, True]
[False, True] or [True, True] = [False or True, True or True] = [True, True]
  

Какой смысл имеет наблюдаемое поведение и как я могу добиться желаемого поведения?

Комментарии:

1. чего вы ожидали [False, True] and [True, True] = [False and True, True and True] ?

2. @juanpa.arrivillaga именно так это работает в R и Fortran. Они оценивают векторы поэлементно.

3. R и Fortran используют массивы, а не простые старые списки (следовательно, почему numpy заполняет пробел)

Ответ №1:

Каждый список оценивается как единое целое. [False, True] имеет значение True, и так оно и есть [True, True] , потому что только пустой список имеет значение False.

and возвращает последний элемент True, но or возвращает первый.

Комментарии:

1. и как мне оценить поэлементно?

2. @rvbarreto вам нужно ввести цикл. zip может быть полезно.

3. Ни один из этих списков не является True . Они просто истинны. Неясно, что вы подразумеваете под True.

4. @superbrain они оба вычисляются как True при использовании в логическом контексте, потому что они не пустые.

5. Я предполагаю, что это может быть правильным, хотя, насколько я знаю, это было бы деталью реализации. В документации if , например, говорится только об истине, а не о True .

Ответ №2:

Python не предоставляет поэлементных операций со списками. Вы можете использовать понимание списка:

 l1 = [False, True] 
l2 = [True, True]
[x and y for x,y in zip(l1, l2)]
#[False, True]
  

Обратите внимание, что np.bitwise_and рекомендуемый в другом месте примерно на порядок медленнее.

Комментарии:

1. Проблема с этим вопросом заключается в том, что list(zip(l1, l2)) == list(l1, l2) поэтому сложно понять, как на самом деле перебирать все

2. @PaulH Я не уверен, что ты имеешь в виду. list(l1, l2) в первую очередь, это незаконно.

3. извините, я имею в виду это list(zip(l1, l2)) == [l1, l2] для приведенных данных примера. Поэтому трудно понять, какие сравнения на самом деле выполняет OP.

Ответ №3:

Вы хотите использовать numpy. Стандартная библиотека python вычисляет:

 bool([False, True]) and bool([True, True])
  

Поскольку оба значения истинны, выбирается последнее (попробуйте 1 and 2 )

если вы сделали:

 import numpy
numpy.bitwise_and([False, True], [True, True])
  

Вы получите то, что хотите.

Если вы не хотите использовать numpy, вам нужно написать представление списка или цикл:

 result = [(x and y) for x, y in zip([False, True], [True, True])]
  

Ответ №4:

Из ссылки:

Выражение x and y сначала вычисляет x; если x равно false, возвращается его значение; в противном случае вычисляется y и возвращается результирующее значение.

Ваше выражение ([False, True] and [True, True]) — это x and y выражение, где вашим x является [False, True] , а вашим y — [True, True] . Теперь x — это false или это true? Также из этой документации:

следующие значения интерпретируются как false: False , None , числовой ноль всех типов и пустые строки и контейнеры (включая строки, кортежи, списки, словари, наборы и замороженные наборы). Все остальные значения интерпретируются как true.

Итак, x равно true, и, следовательно, and операция возвращает y . Это именно то, что вы получили.

Аналогично для or .

Другой способ получить операции с элементами, которые вы хотите:

 >>> x, y = [False, True], [True, True]
>>> from operator import and_, or_
>>> [*map(and_, x, y)]
[False, True]
>>> [*map(or_, x, y)]
[True, True]