2017-01-20 7 views
-1

Я хочу преобразовать все отрицательные значения в список в 0. Для этого у меня есть два разных подхода, тогда как я понимаю, почему первый из обоих подходов работает так, как он делает. Вот пример:Почему это понимание списка преобразует отрицательные значения вместо положительных значений в 0?

values = [200, 400, 50, -20, -100, 90, 780, -600] 
n2z_one = [0 if v < 0 else v for v in values] # approach one 
n2z_two = [v*(v>0) for v in values] #approach two 

Какие результаты в:

values: [200, 400, 50, -20, -100, 90, 780, -600] 
n2z_one: [200, 400, 50, 0, 0, 90, 780, 0] 
n2z_one: [200, 400, 50, 0, 0, 90, 780, 0] 

Моя проблема вот v*(v>0). Разве это не означает, что понимание ищет значения больше, чем 0, и умножает их на 0, вместо поиска значений меньше чем 0 и их умножение на 0?

ответ

3

(v>0) производит булево объект, либо True или False. Логический является подклассом целого с True, имеющими целым значением 1, False целого значением 0:

>>> issubclass(bool, int) 
True 
>>> int(True) 
1 
>>> int(False) 
0 

При использовании булева объекта с арифметическим оператором, он рассматривается как целое число.

Так что если v является меньше или равно 0, (v>0) производит False, и если используется в умножения целое значение 0 используется:

>>> v = 42 
>>> v > 0 
True 
>>> v * True 
42 
>>> v = -81 
>>> v > 0 
False 
>>> v * False 
0 

Используя логическое испытание, как это чистая запутывания , Никогда не используйте его в производственном коде, это только смущает читателя.

Это медленнее, чем условного выражения подход тоже:

>>> from timeit import timeit 
>>> from random import randint 
>>> values = [randint(-10**6, 10**6) for _ in range(1000)] 
>>> timeit('[0 if v < 0 else v for v in values]', 'from __main__ import values', number=10000) 
0.4128753509976377 
>>> timeit('[v*(v>0) for v in values]', 'from __main__ import values', number=10000) 
0.5792852119993768 

Выбор между двумя эталонными (v или 0) на основе булевой тест быстрее, чем умножение. И я упомянул, что использование логического типа создает непонятный беспорядок и никогда не должно использоваться?

+0

Большое спасибо, я никогда не думал о выражении '(v> 0)', производящем логическое выражение, он так много имеет смысл и объясняет почти все. – MrPadlog

1

Булевое число принудительно приводится в числовое число, 1 для True и 0 для False.

Если число больше, вы получите 1, которое умножается на число.

В противном случае вы получите 0, который умножается на любое число: 0.

+0

Как вы думаете, в перспективе перспективы. a if else, если быстрее от * (v> 0) быстрее? Я думаю, если бы еще лучше было работать – Bobby

+0

@Bobby, я бы не смог сказать точно без профилирования, но мое подозрение было бы первым методом, которое было бы пренебрежимо быстрее. – alex

+2

@Bobby: это не быстрее. Это чистая обфускация и никогда не должна использоваться в производственном коде. –

0

v > 0 грубо говоря преобразуется в 1, если это True, 0 в противном случае.

Предположим, что v = 5. Затем мы получаем v*(v>0) == 5*(5>0) == 5*True == 5 * 1 == 5.

Давайте посмотрим, что произойдет, когда v = -5.Тогда v*(v>0) == -5*(-5>0) == -5*False == -5 * 0 == 0

 Смежные вопросы

  • Нет связанных вопросов^_^