6.8. Operatoren

De eerste soort wiskunde die numpy op een ndarray uitvoert, zijn de standaard Python-operatoren. Rekenkundige, vergelijkings- en bitsgewijze operatoren werken allemaal elementsgewijs – elke operator doorloopt de array (of beide arrays) één keer van begin tot eind binnen een enkele bibliotheekaanroep, veel sneller dan de equivalente Python for-lus.

6.8.1. Rekenkunde

+, -, *, /, //, %, ** werken allemaal tussen twee arrays van compatibele vorm, of tussen een array en een scalair:

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])

De resulterende dtype volgt de upcasting-regels die op Dtypes worden beschreven. Integer-arrays lopen rond bij overflow; cast naar een breder dtype vóór de bewerking wanneer dat van belang is.

De matrixvermenigvuldigingsoperator @ is niet geïmplementeerd. Gebruik dot() voor matrix-/vectorproducten.

6.8.1.1. In-place vormen

Elke rekenkundige operator heeft een in-place vorm – +=, -=, *=, /=, %=, **=. De in-place vorm schrijft door de bestaande buffer in plaats van een tijdelijke te reserveren:

b = b + 1            # allocates a temporary the size of b
b += 1               # no temporary

Op een microcontroller is de tweede vorm in wezen verplicht voor elke hot loop.

6.8.2. Bitsgewijs

De bitsgewijze operatoren &, |, ^ werken elementsgewijs op integer-arrays. Toegepast op een float- of complex-array werpen ze TypeError op:

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)

De unaire ~ voert een bitsgewijze NOT uit op een integer-array.

De shift-operatoren << en >> zijn niet aangesloten op het niveau van de Python-operator. De functievormen left_shift() en right_shift() werken wel:

np.left_shift(a, 2)
np.right_shift(b, 1)

6.8.3. Vergelijking

==, !=, <, <=, >, >= retourneren allemaal een bool-ndarray van de broadcast-vorm:

a = np.array([1, 2, 3, 4, 5], dtype=np.uint8)
print(a < 3)
# array([True, True, False, False, False], dtype=bool)

Het booleaanse resultaat is precies wat indexering en Selectie en herschikking consumeren.

6.8.3.1. De zijderegel

De ndarray moet aan de linkerkant van een relationele operator staan bij het vergelijken met een scalair. a > 2 werkt; 2 < a werpt TypeError op. Gebruik voor de symmetrische vorm de functienamen:

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. Unaire operatoren

  • +a – retourneert een kopie van de array.

  • -a – negatie. Op niet-ondertekende dtypes lopen de waarden rond modulo \(2^N\), op dezelfde manier als de binaire operatoren doen.

  • abs(a) – elementsgewijze absolute waarde. Op niet-ondertekende dtypes retourneert het een kopie zonder berekening.

  • ~a – bitsgewijze inversie (alleen integer-arrays).

  • len(a) – retourneert de lengte van de eerste as, conform de Python-sequentieconventie.

6.8.5. Wat ontbreekt

De operatoren aan de rechterkant voor de vergelijking en sommige van de bitsgewijze bewerkingen zijn niet op dezelfde manier geïmplementeerd als de rekenkundige operatoren. Gebruik de functievormen (hierboven) wanneer een ndarray aan de rechterkant zou belanden.

Voor de volledige lijst met ondersteunde operatoren en de upcasting die ze volgen, zie numpy — numpy-compatibele arraybewerkingen.