6.8. Operadores¶
O primeiro tipo de cálculo que o numpy executa sobre um ndarray são os operadores Python padrão. Os operadores aritméticos, de comparação e bit a bit funcionam todos elemento a elemento – cada operador percorre o array (ou ambos os arrays) uma vez do início ao fim dentro de uma única chamada de biblioteca, muito mais rápido do que o laço for Python equivalente.
6.8.1. Aritmética¶
+, -, *, /, //, %, ** funcionam todos entre dois arrays de formato compatível, ou entre um array e um escalar:
a = np.array([1, 2, 3, 4], dtype=np.float)
b = np.array([10, 20, 30, 40], dtype=np.float)
print(a + b) # array([11.0, 22.0, 33.0, 44.0])
print(a * 2) # array([2.0, 4.0, 6.0, 8.0])
print(b - a) # array([9.0, 18.0, 27.0, 36.0])
print(b / a) # array([10.0, 10.0, 10.0, 10.0])
O dtype do resultado segue as regras de upcasting descritas em Dtypes. Arrays inteiros sofrem overflow com wrap-around; converta para um dtype mais largo antes da operação quando isso for importante.
O operador de multiplicação de matrizes @ não é implementado. Use dot() para produtos de matrizes / vetores.
6.8.1.1. Formas in-place¶
Todo operador aritmético tem uma forma in-place – +=, -=, *=, /=, %=, **=. A forma in-place grava diretamente no buffer existente em vez de alocar um temporário:
b = b + 1 # allocates a temporary the size of b
b += 1 # no temporary
Em um microcontrolador, a segunda forma é essencialmente obrigatória para qualquer laço crítico.
6.8.2. Bit a bit¶
Os operadores bit a bit &, |, ^ funcionam elemento a elemento em arrays inteiros. Aplicados a um array float ou complex eles lançam TypeError
a = np.array([0b1100, 0b1010], dtype=np.uint8)
b = np.array([0b1010, 0b1100], dtype=np.uint8)
print(a & b) # array([8, 8], dtype=uint8)
print(a | b) # array([14, 14], dtype=uint8)
print(a ^ b) # array([6, 6], dtype=uint8)
O operador unário ~ realiza o NOT bit a bit em um array inteiro.
Os operadores de deslocamento << e >> não estão conectados no nível de operador Python. As formas em função left_shift() e right_shift() funcionam:
np.left_shift(a, 2)
np.right_shift(b, 1)
6.8.3. Comparação¶
==, !=, <, <=, >, >= retornam todos um ndarray de bool com o formato resultante do broadcast:
a = np.array([1, 2, 3, 4, 5], dtype=np.uint8)
print(a < 3)
# array([True, True, False, False, False], dtype=bool)
O resultado booleano é exatamente o que a indexação e a Seleção e reordenação consomem.
6.8.3.1. A regra do lado¶
O ndarray deve estar à esquerda de um operador relacional ao comparar com um escalar. a > 2 funciona; 2 < a lança TypeError. Para a forma simétrica, use os nomes de função:
np.greater(5, a) # 5 > a, element-wise
np.less(5, a) # 5 < a, element-wise
np.equal(5, a) # 5 == a, element-wise
np.not_equal(5, a) # 5 != a, element-wise
6.8.4. Operadores unários¶
+a– retorna uma cópia do array.-a– negação. Em dtypes sem sinal, os valores sofrem wrap-around módulo \(2^N\), da mesma forma que os operadores binários.abs(a)– valor absoluto elemento a elemento. Em dtypes sem sinal, retorna uma cópia sem cálculo.~a– inversão bit a bit (somente arrays inteiros).len(a)– retorna o comprimento do primeiro eixo, conforme a convenção de sequências do Python.
6.8.5. O que está faltando¶
Os operadores do lado direito para as operações de comparação e algumas das operações bit a bit não são implementados da mesma forma que os operadores aritméticos. Use as formas em função (acima) quando um ndarray ficaria à direita.
Para a lista completa de operadores suportados e o upcasting que eles seguem, consulte numpy — operações de array compatíveis com numpy.