Python Предикаты и условия - PullRequest
0 голосов
/ 25 марта 2020

Пользователь на github сообщил об ошибке в следующем коде, используя режим numba no python:

from numba import njit
import numpy as np

@njit
def foo():
    a = np.ones(1, np.bool_)
    if a > 0:
        print('truebr')
    else:
        print('falsebr')

foo()

Ему сказали, что выражение a > 0 не является предикатом, а скорее условным. Чтобы исправить это, он должен был «Обернуть условные слова в правду для создания предикатов».

Означает ли это, что (a > 0) == True исправит ошибку, возникающую в numba или что-то еще.

https://github.com/numba/numba/pull/3901/commits/598cdd1707fdeb11b8f1d70aef2d3e36ef37bd34. Это исправление для этих типов ошибок в numba?

1 Ответ

2 голосов
/ 25 марта 2020

В Python (не numba) функция работает:

In [412]: def foo(): 
     ...:     a = np.ones(1, np.bool_) 
     ...:     if a > 0: 
     ...:         print('truebr') 
     ...:     else: 
     ...:         print('falsebr') 
     ...:                                                                                      
In [413]: foo()                                                                                
truebr

Но если a - массив с большим количеством значений:

In [414]: def foo(): 
     ...:     a = np.ones(2, np.bool_) 
     ...:     if a > 0: 
     ...:         print('truebr') 
     ...:     else: 
     ...:         print('falsebr') 
     ...:                                                                                      
In [415]: foo()                                                                                
...
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Если я попытаюсь ваша функция в njit я получаю длинный след; слишком долго, чтобы показать или проанализировать, но это, по сути, говорит мне, что это невозможно сделать в режиме njit. Учитывая вышеприведенное значение ошибки, я не удивлен. njit не допускает массив значений just-one Truth.

Как правило, при использовании numba вы должны выполнять итерацию. Это его главная цель - запускать numpy/python задач, которые в противном случае были бы слишком дорогими для повторения. Не рассчитывайте на numba для обработки всех нюансов Python.

Если я изменю функцию для проверки каждого элемента a, она будет работать:

In [421]: @numba.njit 
     ...: def foo(): 
     ...:     a = np.array([True]) 
     ...:     for i in a: 
     ...:         if i > 0: 
     ...:             print('truebr') 
     ...:         else: 
     ...:             print('falsebr') 
     ...:                                                                                      
In [422]: foo()                                                                                
truebr

Оболочка all (или any) также работает:

In [423]: @numba.njit 
     ...: def foo(): 
     ...:     a = np.array([True]) 
     ...:     if (a > 0).all(): 
     ...:         print('truebr') 
     ...:     else: 
     ...:         print('falsebr') 
     ...:                                                                                      
In [424]: foo()                                                                                
truebr
...