Python tablice
Język Programowania

Python tablice w praktyce programisty – indeksowanie, operacje na danych i wydajne przetwarzanie list

Praca z danymi rzadko kończy się na pojedynczej zmiennej. W praktyce prawie zawsze pojawia się potrzeba przechowywania wielu wartości tego samego typu: list liczb, wyników pomiarów, nazw użytkowników, współrzędnych punktów albo danych odczytywanych z pliku. Programista musi wtedy wybrać strukturę, która pozwala wygodnie te dane zapisać, odczytać i przetwarzać bez chaosu oraz bez niepotrzebnego spowalniania programu. W języku Python najczęściej wykorzystuje się do tego listy, krotki oraz tablice numeryczne z bibliotek dodatkowych, dlatego zrozumienie zagadnienia Python tablice ma bardzo praktyczne znaczenie już na początku nauki.

Python tablice w praktyce pracy z danymi sekwencyjnymi i indeksowaniem

W samym Pythonie nie istnieje „tablica” w dokładnie takim znaczeniu jak w języku C, gdzie mamy ciągły blok pamięci o stałym typie elementów. Najczęściej rolę tablicy pełni lista (list), czyli dynamiczna struktura sekwencyjna.

Lista może przechowywać wiele elementów i pozwala na ich zmianę w trakcie działania programu. Można dodawać nowe wartości, usuwać stare, zmieniać kolejność oraz odwoływać się do konkretnego elementu przez indeks.

Indeksowanie zaczyna się od zera. To jeden z najczęstszych błędów początkujących. Jeśli lista ma pięć elementów, ich indeksy to: 0, 1, 2, 3, 4.

Przykład:

OperacjaKodWynik
Utworzenie listyliczby = [10, 20, 30, 40]lista czterech elementów
Odczyt pierwszego elementuprint(liczby[0])10
Odczyt ostatniego elementuprint(liczby[-1])40
Długość listyprint(len(liczby))4

Indeks ujemny oznacza liczenie od końca. -1 to ostatni element, -2 przedostatni itd. W praktyce bardzo wygodne przy analizie logów, danych pomiarowych albo ostatnich rekordów.

W C sytuacja wygląda inaczej. Tablica ma zwykle stały rozmiar i konkretny typ danych.

JęzykKod
Cint liczby[4] = {10, 20, 30, 40};
C++int liczby[4] = {10, 20, 30, 40};
Pythonliczby = [10, 20, 30, 40]

W Pythonie lista jest wygodniejsza, ale ma większy koszt pamięciowy. Przy bardzo dużych zbiorach danych to zaczyna mieć znaczenie.

Istnieje też wycinanie fragmentów listy, czyli slicing. To mechanizm bardzo często używany przy analizie danych.

OperacjaKodWynik
Pierwsze trzy elementyprint(liczby[:3])[10, 20, 30]
Od drugiego do końcaprint(liczby[1:])[20, 30, 40]
Co drugi elementprint(liczby[::2])[10, 30]

Schemat działania można zapisać jako:

WzórZnaczenie
lista[start:stop:krok]fragment od start do stop - 1 co krok

Brak zrozumienia tego zapisu często prowadzi do błędów logicznych, szczególnie przy sortowaniu i przetwarzaniu fragmentów danych.

Różnica między listą, krotką i klasyczną tablicą oraz wpływ na wydajność programu

Nie każda sekwencja danych powinna być listą. Python udostępnia także krotki (tuple) oraz moduł array, a w obliczeniach numerycznych zwykle używa się NumPy.

Krotka jest niemodyfikowalna. Po utworzeniu nie można zmienić jej zawartości. To zaleta, gdy dane mają pozostać stałe.

StrukturaCechy
Lista (list)dynamiczna, modyfikowalna
Krotka (tuple)niemodyfikowalna, szybsza przy odczycie
arrayjednolity typ danych
NumPy arrayszybkie obliczenia numeryczne

Przykład:

TypKod
Listapunkty = [3, 7, 9]
Krotkapunkty = (3, 7, 9)

Jeśli program przechowuje miliony wartości liczbowych, lista może być nieefektywna. Każdy element listy jest obiektem Pythona, co zwiększa zużycie pamięci.

Dla przykładu:

  • lista 1 000 000 liczb całkowitych może zajmować dziesiątki megabajtów więcej niż struktura numeryczna,
  • operacje matematyczne wykonywane element po elemencie są znacznie wolniejsze niż obliczenia wektorowe.

Dlatego w analizie danych, uczeniu maszynowym i symulacjach praktycznie standardem jest NumPy.

Warto też pamiętać o module array, który jest mniej popularny, ale bywa przydatny.

KodZnaczenie
from array import arrayimport modułu
a = array('i', [1, 2, 3, 4])tablica liczb całkowitych

Litera 'i' oznacza typ integer. Dzięki temu dane są przechowywane oszczędniej niż w zwykłej liście.

Python tablice oraz operacje dodawania usuwania i modyfikacji elementów

Najwięcej błędów praktycznych pojawia się właśnie tutaj: program działa, ale wynik jest zły, bo element został dodany nie tam, gdzie trzeba, albo usunięto niewłaściwy indeks.

Podstawowe operacje trzeba znać bez zastanawiania się.

OperacjaKodEfekt
Dodanie na końculista.append(50)dopisanie jednego elementu
Dodanie wielu elementówlista.extend([60, 70])rozszerzenie listy
Wstawienie w środeklista.insert(1, 15)wstawienie na indeks 1
Usunięcie po wartościlista.remove(20)usuwa pierwsze wystąpienie
Usunięcie po indeksielista.pop(2)usuwa element o indeksie 2
Czyszczenielista.clear()usuwa wszystko

Przykład w Pythonie:

Kod
oceny = [3, 4, 5]
oceny.append(6)
oceny[1] = 5
print(oceny)

Wynik:

Wynik
[3, 5, 5, 6]

W C lub C++ takie operacje są bardziej ręczne. Trzeba kontrolować rozmiar tablicy i często kopiować dane.

JęzykKod
C++vector<int> oceny = {3,4,5};
C++oceny.push_back(6);

W praktyce początkujący często używają remove() i zakładają, że usuwa element po indeksie. To błąd. remove() usuwa po wartości, a pop() po pozycji.

Kolejna pułapka to modyfikacja listy podczas iteracji:

Błędny kod
for x in lista:
if x < 0:
lista.remove(x)

To może pominąć część elementów. Bezpieczniej używać nowej listy:

Poprawny kod
lista = [x for x in lista if x >= 0]

To rozwiązanie jest prostsze i zwykle bardziej przewidywalne.

Iteracja po elementach oraz wyszukiwanie wartości bez zbędnych błędów logicznych

Sama obecność danych nie wystarcza. Najczęściej trzeba je przeliczyć, sprawdzić lub przefiltrować.

Podstawowa iteracja:

Kod
for x in liczby:
print(x)

Gdy potrzebny jest indeks:

Kod
for i, x in enumerate(liczby):
print(i, x)

To lepsze niż ręczne zwiększanie licznika.

Suma elementów:

Kod
suma = sum(liczby)

Maksimum i minimum:

Kod
maks = max(liczby)
mini = min(liczby)

Sprawdzenie obecności:

Kod
if 20 in liczby:
print("znaleziono")

Złożoność wyszukiwania w liście jest liniowa:

OperacjaZłożoność
odczyt po indeksieO(1)
wyszukiwanie wartościO(n)
dodanie na końcuśrednio O(1)
wstawienie na początekO(n)

Przy bardzo dużych danych to ma znaczenie. Jeśli stale sprawdzamy obecność elementu, czasem lepszy będzie zbiór (set) niż lista.

Python tablice przy obliczeniach numerycznych i współpracy z biblioteką NumPy

Przy obliczeniach matematycznych zwykła lista szybko staje się niewygodna. Dodawanie dwóch list nie oznacza dodawania elementów, tylko ich łączenie.

KodWynik
[1,2] + [3,4][1,2,3,4]

Dla matematyki to zwykle nie to, czego oczekujemy.

Dlatego używa się NumPy.

Kod
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(a + b)

Wynik:

Wynik
[5 7 9]

To już działanie wektorowe.

Średnia:

Kod
print(np.mean(a))

Odchylenie standardowe:

Kod
print(np.std(a))

Wzory wykorzystywane najczęściej:

WzórZnaczenie
\bar{x} = \frac{1}{n}\sum_{i=1}^{n}x_iśrednia arytmetyczna
s = \sqrt{\frac{1}{n}\sum_{i=1}^{n}(x_i-\bar{x})^2}odchylenie standardowe

xˉ=1ni=1nxi\bar{x} = \frac{1}{n}\sum_{i=1}^{n}x_ixˉ=n1​∑i=1n​xi​

NumPy jest standardem w:

  • analizie danych,
  • przetwarzaniu sygnałów,
  • statystyce,
  • modelach predykcyjnych,
  • grafice naukowej,
  • systemach uczenia maszynowego.

Bez tej biblioteki większe obliczenia szybko stają się wolne i trudne do utrzymania.

Najczęstsze pułapki praktyczne i błędy, które kosztują najwięcej czasu

Pierwszy problem to kopiowanie list.

KodEfekt
a = [1,2,3]lista źródłowa
b = anie kopia, tylko drugi odnośnik

Zmiana b zmienia też a.

Poprawnie:

Kod
b = a.copy()

Drugi problem to domyślne argumenty funkcji.

Błędny kod
def dodaj(x, lista=[]):
lista.append(x)
return lista

Lista zostaje zapamiętana między wywołaniami funkcji.

Bezpieczniej:

Poprawny kod
def dodaj(x, lista=None):
if lista is None:
lista = []

Trzeci problem to przekonanie, że szybciej znaczy lepiej. Czasem prosty for jest czytelniejszy niż skomplikowane jednolinijkowe konstrukcje.

Kod ma być przede wszystkim zrozumiały za pół roku, nie tylko krótki dziś.

FAQ

Czy lista i tablica to dokładnie to samo?

Nie. W codziennej rozmowie często używa się tych słów zamiennie, ale technicznie lista w Pythonie jest dynamiczną strukturą obiektową, a klasyczna tablica z C to zwykle ciągły blok pamięci o stałym typie i rozmiarze.

Kiedy lepiej użyć krotki zamiast listy?

Gdy dane nie powinny się zmieniać, na przykład współrzędne punktu, stałe konfiguracje albo wartości zwracane przez funkcję. Krotka jest bezpieczniejsza logicznie i zwykle trochę lżejsza.

Czy NumPy zawsze jest lepsze od list?

Nie. Dla kilku elementów zwykła lista jest prostsza. NumPy daje dużą przewagę przy większych zbiorach danych i obliczeniach numerycznych wykonywanych masowo.

Dlaczego indeksowanie zaczyna się od zera?

To wynika z historycznej konstrukcji języków programowania i sposobu adresowania pamięci. Indeks oznacza przesunięcie od początku struktury, więc pierwszy element ma przesunięcie równe zero.

Czy można przechowywać różne typy danych w jednej liście?

Tak. Python na to pozwala, ale w praktyce często pogarsza to czytelność kodu i utrudnia przetwarzanie danych. W większości zastosowań lepiej zachować spójność typów.

Co jest szybsze: lista czy set przy wyszukiwaniu?

Dla sprawdzania obecności elementu zwykle szybszy jest set, ponieważ operacja ma średnio złożoność bliską O(1), podczas gdy lista wymaga najczęściej O(n).

Dobra praca z sekwencjami danych nie polega na pamiętaniu nazw metod, tylko na rozumieniu kosztu operacji i skutków wyboru struktury. To właśnie decyduje, czy program pozostanie prosty i przewidywalny, czy po kilku tygodniach zacznie generować trudne do znalezienia błędy.

Źródło Foto: Freepik

Dodaj komentarz