Dict, set, list!

Przy okazji niedawnego code review dostałem pytanie, czemu w skrypcie napisanym w Pythonie nie korzystam z obiektu typu set, tylko z dict. Chodziło o cache na kilka tysięcy elementów, odpytywany kilkaset tysięcy razy. Z przyzerowym hit ratio. Zdziwiłem się, bo kojarzyłem, że czytelna konstrukcja wykorzystująca in dla obiektu typu list

data = [x for x in range(1000)]
y = 1001
if y in data:
    print("Hit")

jest raczej wolna. Zwłaszcza w porównaniu z nieco mniej czytelnym wariantem z użyciem dict:

data = {x: True for x in range(1000)}
y = 1001
if data.get(y):
    print("Hit")

Odpisałem o co chodziło i usłyszałem, że przecież set jest szybki. Coś mi zaświtało. Bo niby set jest bardziej podobny w użyciu do listy, ale pod spodem ma parę ciekawych właściwości. Zresztą, gdy poprosimy LLM o optymalizację pod kątem szybkości, otrzymamy coś w stylu[1]:

data = {x for x in range(1000)} # Converted 'data' to a set
y = 1001
if y in data:  # Checking membership still works the same way
    print("Hit")

Różnice w czasie wykonania możemy zgrubnie i niezbyt elegancko sprawdzić w następujący sposób:

Jak już jesteśmy przy tego typu ciekawostkach. A co jeśli mamy w cache ciągi znaków i chcemy sprawdzić, czy nasz ciąg znaków nie kończy się jednym z ciągów z cache? LLM poproszony o optymalizację znowu podpowiada, że lepszy jest set. Ale nieoczekiwanie sugeruje też wykorzystanie regexpów. I co? Ku mojemu zaskoczeniu regexp w stylu

pattern = re.compile("("+"|".join(our_set)+")"$")
return bool(pattern.search(tested_value))

okazuje się najszybszym rozwiązaniem! Nie to, że uważam regexpy za szczególnie wolne, co to, to nie. Oczywiście pattern wykonujemy raz, nie dla każdej testowanej wartości.

Dalsza lektura:
O’reily High performance Python Dictionaries and Sets

[1] Tak, różnica niezbyt rzuca się w oczy przy takim zapisie. Mało widać różnicę między dict a set. Kiedyś już o tym wspominałem. Czytelniejszy zapis – którego chyba nikt nie używa – tamże.

Daft Social – anti social network

Dziś dowiedziałem się o serwisie Daft Social. Przyznaję, że pomysł jest interesujący. Jest to minimalistyczne medium społecznościowe. Czy też antyspołecznościowe. Wielu rzeczy nie ma. Na przykład nie ma możliwości interakcji z treścią. Nie tylko przez innych, ale nawet sam autor nie ma możliwości ani edycji, ani usunięcia zamieszczonego wpisu. Nie ma tytułu, nie ma hashtagów. Nie ma dokładnego czasu zamieszczenia wpisu – jest tylko data. Z rzeczy które są – jest dostępny RSS.

Tworzenie wpisów czy też cała interakcja z platformą także jest minimalistyczna. Wpisy tworzymy poprzez… wysyłanie maili, a cała treść wpisu jest w jego temacie. Body maila nie ma już żadnego znaczenia. Można zamieszczać linki do stron oraz obrazki przez podanie URLi. Nadal w temacie maila.

Niestety, brakuje też security. Jeśli chodzi o zabezpieczenia, to mamy tylko losowego maila, na którego wysłanie powoduje dodanie wpisu. Czyli pojedynczy, stały sekret. Bez możliwości jego zmiany, bez 2FA. Bez możliwości przypomnienia – choć tu podanych jest parę tricków. Bez możliwości ograniczenia, z jakiego adresu email mają być przyjmowane maile.

Mimo wszystko pomysł mi się spodobał. Na tyle, że założyłem konto na Daft Social. Nie wiem jeszcze czy i jak będę korzystał. Póki co planuję wysyłać tam powiadomienia o nowych wpisach na blogu, podobne do tych, które trafiają na Blablera.

Bieganie i rower 2023 – podsumowanie

Bieganie w roku 2023 zacząłem wcześnie, bo już 8 stycznia. Zupełnie tak samo jak w zeszłym roku! Biegałem nawet regularnie, więc w maju osiągnąłem poprzednią formę i zacząłem poprawiać wyniki. Biegi w okolicach 8 km. Szło dobrze, zastanawiałem się nawet ile przebiegnę w tym roku i czy będzie nowy rekord. Niestety zaraz dowiemy się, czemu się nie udało. I nie pomogło nawet szalone firmowe wyzwanie dwa miesiące przed świętami, w którym już zupełnie na ludzie dorzuciłem w nim 44 km. Byłoby więcej, ale przeszkodziło i zdrowie – przeziębienie, i aktywna końcówka roku pod innymi względami.
Bieganie 235 km, 38 aktywności, 24h w ruchu.

Biegało mi się tak dobrze, że postanowiłem dołożyć rower. Uruchomiłem go w tym roku bardzo późno, bo dopiero 30 czerwca. I to był błąd. Rower zupełnie skanibalizował bieganie. Tym bardziej, że gdy jest upał, to dużo przyjemniej jechać rowerem, niż biec. Zacząłem jeździć nie tylko komunikacyjnie, ale i rekreacyjnie trasy po ok. 30 km. Wada? Nie było czasu na bieganie. I jakoś forma biegowa siadła.
69 aktywności, 411 km, 33h w ruchu.

Jak widać, dobry początek roku jeszcze o niczym nie świadczy i nie można dzielić skóry na niedźwiedziu. Rower nie zastąpi biegania. Miał być progres, był regres. Chociaż jak sprawdziłem poprzednie parę lat, a nie tylko 2022, to w sumie bez dramatu.

Ale jest i sukces. Pierwszy bieg w styczniu, bieganie zimą na początku roku. Oraz trochę pobiegane pod koniec roku. Ostatni(?) bieg 17 grudnia. Czyli udało się biegać przez cały rok.