Also mich hat mal interessiert, wie das Python Slicing sich zeitlich so verhält und habe in einem Jupyter Notebook etwas rumgespielt.
Da das Slicing ja wohl auf C-Ebene realisiert ist, ist es 20x schneller als wenn man es per List Comprehension nachbaut.
Beides hat O(n).
Numpy Slicing hat O(1), da keine Kopie der Daten erzeugt werden.
Ist also extrem schnell. Je nach Slicegröße Faktor 15 bis 160. (in deiner range(10000))
Benötigt man eine Kopie der Daten, dann haben wir wieder O(n) und "nur" noch einen Faktor 12x.
Es hängt also davon ab, was du mit den Slices machen willst.
Aber grundsätzlich bist du mit Numpy im Turbo-Modus
Code: Alles auswählen
arr = [_ for _ in range(10000)]
%timeit sli = arr[0:1000]
%timeit sli = arr[9000:10000]
# gleich schnell ob am Anfang oder Ende der Liste
3 µs ± 49.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
2.96 µs ± 10.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
# slicing nachbilden durch list comprehension
%timeit sli = [arr[i] for i in range(0, 1000)]
%timeit sli = [arr[i] for i in range(9000, 10000)]
# ca 20x langsamer
60.4 µs ± 1.34 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
61.7 µs ± 543 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
# verdopplung der slice grösse
%timeit sli = arr[0:2000]
%timeit sli = arr[8000:10000]
# ca. verdopplung der zeit
6.31 µs ± 123 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
6.27 µs ± 55.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit sli = [arr[i] for i in range(0, 2000)]
%timeit sli = [arr[i] for i in range(8000, 10000)]
# gleiches gilt für die list comprehension
122 µs ± 3.82 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
125 µs ± 4.02 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit sli = arr[0:9000]
35.7 µs ± 183 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
import numpy as np
arr = np.arange(10000)
# Numpy slicing hat O(1)? wie das?
%timeit sli = arr[0:1000] # 15x schneller bei 1000 Elementen
%timeit sli = arr[2000:4000] # 30x schneller bei 2000 Elementen
%timeit sli = arr[0:9000] # 160x schneller bei 9000 Elementen
249 ns ± 3.23 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
242 ns ± 10.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
235 ns ± 3.26 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
# Numpy slicing erzeugt nur ein Abbild/View
arr = np.arange(10)
sli = arr[:5]
sli[0] = 100
print(sli, arr)
# Veränderungen des Slices verändern das ursprüngliche Array
[100 1 2 3 4] [100 1 2 3 4 5 6 7 8 9]
# Python slicing erzeugt ein neues Objekt
arr = [_ for _ in range(10)]
sli = arr[:5]
sli[0] = 100
print(sli, arr)
[100, 1, 2, 3, 4] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# numpy.copy() erzeugt ein neues Objekt
arr = np.arange(10)
sli = arr[:5].copy()
sli[0] = 100
print(sli, arr)
[100 1 2 3 4] [0 1 2 3 4 5 6 7 8 9]
arr = np.arange(10000)
%timeit sli = arr[0:9000].copy()
2.56 µs ± 17 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
# und ist dann nur noch 12x schneller als Python slicing