Tablice
Tablice w językach programowania są sposobem przechowywania wielu wartości pod jedną nazwą. W klasycznych językach niskopoziomowych tablica oznacza zwykle ciąg elementów tego samego typu, zapisanych w spójnym obszarze pamięci. W Python sytuacja jest bardziej złożona – pojęcie „tablicy” jest potoczne i obejmuje kilka różnych struktur danych.
W Python podstawowe „tablice” to: listy, krotki i słowniki. Każda z tych struktur ma inną semantykę, inne właściwości i inne zastosowania. Wszystkie należą do kategorii Python: struktury danych wbudowanych w język. W dalszej części tekstu traktuję je jako Tablice, bo pełnią rolę kolekcji elementów.
Spis treści
Tablice Python jako dynamiczne kontenery obiektów – czym są i jak są reprezentowane w pamięci
W Python nie istnieje klasyczna tablica znana z języka C jako int arr[10]. Zamiast tego mamy obiekty dynamiczne. Każda Tablica Python (lista, krotka, słownik) przechowuje referencje do obiektów, a nie same wartości.
To oznacza kilka rzeczy:
- Elementy mogą mieć różne typy.
- Rozmiar może się zmieniać w trakcie działania programu (dla list i słowników).
- Operacje nie zawsze są stałoczasowe – zależy to od implementacji.
W uproszczeniu:
- Lista → dynamiczna tablica referencji.
- Krotka → niemodyfikowalna sekwencja referencji.
- Słownik → tablica mieszająca (hash table).
W odróżnieniu od języka C, Python nie wymaga deklarowania rozmiaru. Zarządzanie pamięcią jest automatyczne.
Tablice – listy w Python jako dynamiczne sekwencje indeksowane liczbami całkowitymi
Lista to najczęściej używana Tablica Python. Jest:
- uporządkowana,
- indeksowana od 0,
- mutowalna (można zmieniać elementy),
- dynamiczna (rozmiar może się zmieniać).
Tworzenie listy Python – podstawowe sposoby
Najprostsza forma:
a = [1, 2, 3]
Pusta lista:
a = []
Z użyciem konstruktora:
a = list()
Lista z zakresu:
a = list(range(5))
Wynik:
[0, 1, 2, 3, 4]
Dostęp do elementów
a = [10, 20, 30]
print(a[0]) # 10
print(a[-1]) # 30
Indeksowanie ujemne liczy od końca.
Modyfikacja elementów
a = [1, 2, 3]
a[1] = 100
Lista zmieni się na [1, 100, 3].
Odpowiednik w C – klasyczna tablica statyczna
#include <stdio.h>int main() {
int a[3] = {1, 2, 3};
printf("%d\n", a[1]);
return 0;
}Tutaj:
- rozmiar jest stały,
- elementy mają ten sam typ,
- pamięć jest ciągła.
Odpowiednik w C++ – std::vector jako dynamiczna tablica
#include <iostream>
#include <vector>int main() {
std::vector<int> a = {1, 2, 3};
a.push_back(4);
std::cout << a[0] << std::endl;
return 0;
}
std::vector jest bliższy liście Python niż klasyczna tablica C.
Tworzenie tablic – krotek jako niemodyfikowalnych sekwencji danych
Krotka (tuple) to struktura podobna do listy, ale niemodyfikowalna.
Tworzenie krotki
t = (1, 2, 3)
Jednoelementowa krotka:
t = (5,)
Bez przecinka Python potraktuje to jako zwykłą wartość.
Można też zapisać bez nawiasów:
t = 1, 2, 3
Cechy krotki
- nie można zmienić elementu,
- nie można dodać nowego elementu,
- można ją indeksować jak listę.
t = (10, 20, 30)
print(t[1])
Dlaczego używać krotek
- Dane stałe logicznie (np. współrzędne punktu).
- Klucze w słownikach.
- Optymalizacja – są nieco lżejsze niż listy.
Wewnętrznie krotka nie musi zarządzać nadmiarową przestrzenią jak lista, bo nie zmienia rozmiaru.
Tworzenie tablic – słowników jako struktur klucz-wartość opartych o funkcję mieszającą
Słownik w Python to implementacja tablicy haszującej.
Tworzenie słownika
d = {"a": 1, "b": 2}Pusty słownik:
d = {}Z konstruktora:
d = dict()
Dostęp do elementów
print(d["a"])
W słowniku nie używa się indeksów liczbowych, tylko kluczy.
Właściwości
- klucze muszą być niemodyfikowalne,
- dostęp do elementu jest średnio O(1),
- brak gwarancji fizycznego uporządkowania (choć Python zachowuje kolejność wstawiania).
Przykład działania funkcji mieszającej
- Klucz → funkcja hash.
- Hash → indeks w tablicy.
- Kolizje rozwiązywane przez mechanizm wewnętrzny (np. otwarte adresowanie).
Tablice – operacje wspólne dla list i krotek oraz ich znaczenie w przetwarzaniu danych
Sekwencje w Python mają wspólne operacje:
- długość:
len(a) - iteracja: for x in a:
print(x) - wycinanie (slicing): a[1:3]
tablica string
W Python łańcuch znaków (str) działa jak niemodyfikowalna sekwencja znaków, czyli jak krotka znaków.
s = "abc"
print(s[0])
To również przykład sekwencji indeksowanej.
Automatyczne uzupełnianie tablic – mechanizmy generowania elementów i inicjalizacji zbiorczej
Automatyczne uzupełnianie tablic oznacza tworzenie struktur na podstawie reguły.
1. List comprehension
a = [x * 2 for x in range(5)]
Wynik:
[0, 2, 4, 6, 8]
Mechanizm:
- iteracja po sekwencji,
- obliczenie wyrażenia,
- zapis do nowej listy.
2. Inicjalizacja powielona
a = [0] * 5
Uwaga: dla obiektów zagnieżdżonych to tworzy referencje do tego samego obiektu.
Błąd:
a = [[0] * 3] * 3
a[0][0] = 9
Zmieni wszystkie wiersze, bo wskazują na ten sam obiekt.
Poprawnie:
a = [[0 for _ in range(3)] for _ in range(3)]
3. Generowanie słowników
d = {x: x*x for x in range(5)}4. Funkcja enumerate
a = ["a", "b", "c"]for i, v in enumerate(a):
print(i, v)
To częsty element Python: lista komend używanych przy pracy z listami.
Tablice Python a złożoność obliczeniowa podstawowych operacji i ich konsekwencje praktyczne
Lista:
- dostęp przez indeks: O(1)
- append: amortyzowane O(1)
- insert w środku: O(n)
- usunięcie z początku: O(n)
Słownik:
- dostęp: średnio O(1)
- wstawienie: średnio O(1)
- iteracja: O(n)
Krotka:
- dostęp: O(1)
- brak operacji modyfikujących
Przy dużych zbiorach danych różnice stają się istotne.
Python: lista komend i python: komendy lista najczęściej używane przy pracy z listami
Najważniejsze operacje:
a.append(x)
a.insert(i, x)
a.remove(x)
a.pop()
a.sort()
a.reverse()
Sortowanie:
a.sort()
lub
b = sorted(a)
sort() modyfikuje listę, sorted() tworzy nową.
Pułapki i częste błędy przy pracy z tablicami w Python
- Mylenie kopii z referencją:
b = a
To nie kopia, tylko druga referencja.
Poprawnie:
b = a.copy()
- Modyfikacja listy podczas iteracji.
- Używanie listy zamiast słownika przy wyszukiwaniu po kluczu.
- Zapominanie o przecinku w jednoelementowej krotce.
- Błędne tworzenie wielowymiarowych struktur przez mnożenie list.
Tablice – znaczenie struktur sekwencyjnych i asocjacyjnych w projektowaniu algorytmów
Tablice w Python (listy, krotki, słowniki) są podstawą budowy algorytmów:
- sortowanie,
- wyszukiwanie,
- zliczanie częstości,
- implementacja stosu i kolejki,
- reprezentacja grafów (lista sąsiedztwa jako słownik list).
Przykład reprezentacji grafu:
graf = {
1: [2, 3],
2: [4],
3: [],
4: []
}Tu słownik mapuje wierzchołek na listę sąsiadów.
Zrozumienie, czym są listy, krotki i słowniki, oraz jakie mają właściwości czasowe i semantyczne, jest warunkiem poprawnego projektowania programów w Python. Tablice w tym sensie nie są jedną strukturą, lecz zestawem mechanizmów przechowywania danych, które trzeba dobierać świadomie do konkretnego problemu.