Co To Jest Tabela Haszująca? Haszowanie I Kolizje Wyjaśnione

Wyszukanie klucza w Pythonowym dict z dziesięcioma wpisami zajmuje tyle samo czasu, co w dict z dziesięcioma milionami. To nie wynika z szybkości języka. Pythonowy dict, Javowy HashMap i Map w JavaScript to wszystko tabele haszujące, a cały ten projekt istnieje po to, by wyszukiwanie, wstawianie i usuwanie działały średnio w O(1). Notacja Big O nazywa to wyszukiwanie “czasem stałym”. Oto mechanizm, który na to zasługuje. Jak tabela haszująca zmienia klucz w indeks tablicy Tabela haszująca to tablica plus funkcja, która zmienia klucz w pozycję w tej tablicy. ...

4 listopada 2026 · 7 min · 1420 słów · SpaghettiCoder

Mock, Stub, Fake i Spy: Test Doubles Wyjaśnione

Test dla place_order potrzebuje bramki płatności, klienta SMS i kalkulatora podatku. Podłącz prawdziwe zależności i każde uruchomienie testu obciąży kartę i wyśle SMS na prawdziwy numer. Test jednostkowy ma działać w milisekundach, bez sieci, więc wszystkie trzy trzeba czymś zastąpić. To “coś innego” ma pięć odmian, każda rozwiązuje inny problem, a traktowanie ich jako wymienne jest powodem, dla którego spory “po prostu zmockuj to” w code review nie mają końca. ...

2 listopada 2026 · 7 min · 1455 słów · SpaghettiCoder

Wyrażenia Regularne Wyjaśnione: Jak Naprawdę Działa Regex

<.+> dla <b>bold</b> and <i>italic</i> nie znajduje <b>. Znajduje cały ciąg, od pierwszego < do samego ostatniego >. Nic nie jest zepsute. To właśnie ma robić zachłanny (greedy) kwantyfikator, i to jest też najczęstszy błąd typu “regex matchuje zbyt dużo”. Gdy już wiesz, co silnik robi podczas czytania wzorca, ten błąd i większość jego krewnych przestają być zagadką. Jak silnik regex czyta twój wzorzec Silnik regex nie porównuje wzorca z ciągiem tak, jak porównuje się dwa ciągi pod kątem równości. Silniki, które używasz codziennie (re w Pythonie, RegExp w JavaScript, PCRE, .NET, Java) są regex-directed: przechodzą przez wzorzec od lewej do prawej, token po tokenie, i dla każdego tokenu próbują skonsumować znaki z ciągu w aktualnej pozycji. Gdy token się dopasuje, silnik przesuwa wskaźnik wzorca i wskaźnik ciągu. Gdy token zawodzi, silnik robi backtracking: wraca do ostatniego miejsca, w którym miał wybór, na przykład kwantyfikator, który mógł dopasować mniej znaków, albo gałąź alternatywy, której jeszcze nie spróbował, i wybiera drugą opcję. ...

28 października 2026 · 7 min · 1393 słów · SpaghettiCoder

Co To Jest Unicode i Jak Działa Kodowanie UTF-8

Otwórz plik zapisany w UTF-8 w narzędziu, które zakłada inne kodowanie, i café zmienia się w café. Bajty na dysku się nie zmieniły. Zmieniła się tylko reguła odczytu, czyli sposób zamiany bajtów z powrotem na znaki, a te dwie reguły różnie rozumieją, co znaczy bajt 0xC3. Większość błędów z “dziwnymi znakami” ma to samo źródło: połamane nazwy plików, zmasakrowane formularze, emoji, które wywala insert do bazy danych, dwa stringi wyglądające identycznie, ale różne w porównaniu. Za każdym z nich stoi ta sama pomyłka: mylenie Unicode z UTF-8, dwóch zupełnie różnych rzeczy. ...

20 października 2026 · 7 min · 1438 słów · SpaghettiCoder

Czym Jest TDD i Jak Działa Cykl Red-Green-Refactor

Test napisany po kodzie zwykle sprawdza to, co kod robi, a nie to, co miał robić. Programowanie sterowane testami (TDD) naprawia to, odwracając kolejność: piszesz test, patrzysz, jak nie przechodzi, a potem piszesz najmniejszy możliwy kod, który sprawia, że test przechodzi. Ponieważ test istnieje przed kodem, który sprawdza, nie może po cichu uznać za poprawne tego, co akurat zwróci kod. Kent Beck sformalizował ten cykl jako red, green, refactor w swojej książce z 2002 roku Test-Driven Development: By Example. Nazwa się przyjęła. ...

18 października 2026 · 6 min · 1277 słów · SpaghettiCoder

Rekurencja Wyjaśniona: Kiedy ją Stosować, a Kiedy Nie

Funkcja, która wywołuje sama siebie, ma maksymalną głębokość, i jest ona mniejsza niż większość się spodziewa: 1000 wywołań w CPython domyślnie, w okolicach 10 000-15 000 w Node i silnikach przeglądarek, zależnie od tego, jak dużo zajmuje każda ramka. Przekroczenie tego limitu nie zwalnia programu. Program się wysypuje. Python zgłasza RecursionError: maximum recursion depth exceeded; JavaScript zgłasza RangeError: Maximum call stack size exceeded. Oba błędy mają tę samą przyczynę, a gdy już ją zobaczysz, będziesz wiedzieć, kiedy rekurencja jest właściwym narzędziem, a kiedy staje się ryzykiem. ...

13 października 2026 · 7 min · 1285 słów · SpaghettiCoder

Zasady SOLID Wyjaśnione na Przykładach w Pythonie

Klasa, która zapisuje użytkownika w bazie danych, wysyła mu powitalny email i formatuje rachunek, jest jedną zmianą od zepsucia dwóch funkcji, z którymi nie ma nic wspólnego. Zmieniasz szablon emaila i ryzykujesz zapis do bazy. Zmieniasz układ rachunku i ryzykujesz email. SOLID to pięć zasad, które atakują ten rodzaj splątania z różnych stron, i łączy je jedna idea: klasa powinna mieć jeden powód do zmiany, a reszta kodu powinna zależeć od tego, co element obiecuje robić, nie od tego, jak to robi. ...

10 października 2026 · 9 min · 1750 słów · SpaghettiCoder

Co To Jest Race Condition i Jak Ją Naprawić

Dwa requesty trafiają na ten sam endpoint “wypłać 100€” z różnicą pół milisekundy. Konto ma 150€. Oba requesty czytają ten sam stan konta, oba widzą wystarczające środki, oba zostają zatwierdzone, oba odejmują 100€. Konto kończy na -50€, a żadna ścieżka w kodzie nie powinna do tego doprowadzić. To jest race condition: wynik zależy od tego, która operacja skończy się pierwsza, a to, co było “pierwsze”, nigdy nie zależało od kodu. ...

9 października 2026 · 8 min · 1690 słów · SpaghettiCoder

Dekoratory w Pythonie Wyjaśnione z Przykładami

Co dekorator naprawdę robi z twoją funkcją Chcesz zmierzyć czas każdej funkcji, która wywołuje wolne zewnętrzne API. Możesz wkleić wywołania time.perf_counter() do każdej z nich albo napisać pomiar raz i stosować go wszędzie. Dekorator to druga opcja: to funkcja, która bierze inną funkcję, owija ją dodatkowym zachowaniem i zwraca owiniętą wersję pod oryginalną nazwą. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import time def timed(func): def wrapper(*args, **kwargs): start = time.perf_counter() result = func(*args, **kwargs) elapsed = time.perf_counter() - start print(f"{func.__name__} took {elapsed:.3f}s") return result return wrapper @timed def fetch_price(ticker): time.sleep(0.2) # zastępuje wywołanie sieciowe return 142.50 fetch_price("AAPL") # fetch_price took 0.201s @timed nad def fetch_price to skrót od fetch_price = timed(fetch_price). Python wywołuje timed raz, zaraz po zdefiniowaniu fetch_price, i przypisuje nazwę fetch_price do tego, co zwraca timed. To jest cała robota, jaką wykonuje @. ...

7 października 2026 · 6 min · 1185 słów · SpaghettiCoder

Czemu 0.1 + 0.2 Nie Daje 0.3: Liczby Zmiennoprzecinkowe

Wpisz 0.1 + 0.2 w shellu Pythona i nie dostaniesz 0.3. Dostaniesz 0.30000000000000004. Spróbuj w JavaScript, Java, Go, C albo Rust i wyjdzie ten sam siedemnastocyfrowy ogon. Każdy z tych języków robi dokładnie to, co nakazuje standard sprzętowy. Liczba, która wymagałaby nieskończenie wielu cyfr binarnych, jest ściskana do 64 bitów i coś musi ustąpić. Czemu 0.1 nie da się zapisać dokładnie w binarnym systemie Komputery zapisują liczby zmiennoprzecinkowe w systemie dwójkowym. W systemie dwójkowym ułamek 1/10 ma rozwinięcie okresowe, tak jak 1/3 powtarza się bez końca w systemie dziesiętnym (0.3333...). Zapisane w całości, 0.1 w binarnym zaczyna się tak: ...

6 października 2026 · 5 min · 1033 słów · SpaghettiCoder