<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://niedzwiedz.blog/feed.xml" rel="self" type="application/atom+xml" /><link href="https://niedzwiedz.blog/" rel="alternate" type="text/html" /><updated>2026-02-03T18:16:02+00:00</updated><id>https://niedzwiedz.blog/feed.xml</id><title type="html">Jan “Niedźwiedź” Sikorski</title><subtitle>Programista, ex-policjant, erpegowiec, wspinacz, początkujący pisarz, lewak.</subtitle><author><name>Niedźwiedź</name></author><entry><title type="html">Ten straszny LRAD</title><link href="https://niedzwiedz.blog/policja/2026/02/03/nielegalny-LRAD.html" rel="alternate" type="text/html" title="Ten straszny LRAD" /><published>2026-02-03T07:48:53+00:00</published><updated>2026-02-03T07:48:53+00:00</updated><id>https://niedzwiedz.blog/policja/2026/02/03/nielegalny-LRAD</id><content type="html" xml:base="https://niedzwiedz.blog/policja/2026/02/03/nielegalny-LRAD.html"><![CDATA[<p>Muszę powiedzieć, że niedawno zakręciła mi się łezka w oku. Przy okazji policyjnego zabezpieczenia Marszu Niepodległości, po raz kolejny pojawiły się oskarżenia o policyjne prowokacje.</p>

<p>To samo w sobie może budzic nostalgię, bo przecież od kiedy marsz się odbywa, jego uczestnicy czują się sprowokowani policyjną obstawą. Ale tym razem pojawiło się coś jeszcze.</p>

<p>Bowiem pomiędzy oskarżeniami o prowokacyjną obecnośc, a zarzutami o upolitycznienie, okazywane publikacją wizerunku osób łamiących prawo, pojawiła się jeszcze <a href="https://www.facebook.com/share/p/14WUA7UMpxp/" target="_blank">narracja o krwawej rozprawie, jaką stołeczna Policja, i wydający im rozkazy Rafał Trzaskowski, mieli zgotowac patriotom</a>.</p>

<p>Oto bowiem, z czeluści parkingu Oddziału Prewencji KSP wyciągnięto potężną, okrutną i zakazaną przez prawo broń: LRAD - środek przymusu obezwładniający potęgą fal dźwiękowych.</p>

<p>Co więcej, broń ta budzi grozę samą swoją obecnością. Policja nie musi jej użyc, nie musi nawet grozic jej użyciem, ani w żaden sposób się do tego szykowac. Wystarczy widok terenowego samochodu, z zamontowanym na pace urządzeniem, by miec świadomośc, że oto jesteśmy świadkami groźnej prowokacji. Że funkcjonariusze tylko czekają by uderzyc w zgromadzonych, korzystających jedynie ze swoich konstytucyjnych praw.</p>

<p>I zapytacie teraz, przygnieceni moim kwiecistym opisem, skąd wzięła się ta nostalgia z pierwszego akapitu? Bowiem dokładnie takie same oskarżenia pojawiały się <a href="https://oko.press/policja-przywiozla-kontrmanifestancje-smolenska-sprzet-ogluszania-mowi-ze-by-ogluszac" target="_blank">kilka lat temu</a> , kiedy to druga strona politycznej barykady była u władzy, a obecnie rządzący rzucali w zasadzie identyczne oskarżenia. A jak jest naprawdę?</p>

<p><img src="/img/posts/2026-02-03/lrad1.jpg" />
<em>
    fot. Policja.gov.pl
</em></p>

<h2 id="co-to-jest-lrad">Co to jest LRAD?</h2>

<p>Nie będę się tu rozpisywał o dokładnej historii urządzenia. Jeśli was to ciekawi, możecie zerkną na stronę <a href="https://genasys.com/blog/lrad-is-the-de-facto-standard-for-long-range-hailing-devices-and-heres-why/" target="_blank">producenta</a>, albo <a href="https://theconversation.com/whats-an-lrad-explaining-the-sonic-weapons-police-use-for-crowd-control-and-communication-177442" target="_blank">tutaj</a>.</p>

<p>W dużym skrócie, zupełnie chyba wystarczającym dla tych rozważań: jest to urządzenie zaprojektowane do przekazywania komunikatów głosowych na duże odległości. Może podać wezwanie do rozejścia się, albo inne polecenie do grupy ludzi odległej od nas o kilkaset metrów, nawet jeśli w otoczeniu są inne, głośne źródła dźwięku (np. Wybuchające petardy, albo inne grupy, wznoszące okrzyki).</p>

<p>Szybko jednak okazało się, że odpowiednie parametry (częstotliwość, amplituda) sprawiają, że “odbiorca” takiego sygnału zaczyna czuć solidny dyskomfort. A to oznaczało, że można o LRAD myśleć jako o środku przymusu bezpośredniego.</p>

<p>I to całkiem użytecznym, bo działającym na odległość, nie wymagającym widocznej przemocy, a jednocześnie skutecznie działającym na duże skupiska ludzi.</p>

<p><img src="/img/posts/2026-02-03/lrad4.jpg" />
<em>
    fot.  Adam Kliczek, <a href="http://memoriesstay.com">http://memoriesstay.com</a> (CC-BY-SA-3.0)
</em></p>

<h2 id="skąd-lrad-w-polsce">Skąd LRAD w Polsce?</h2>

<p>W 2010 roku, większość ludzi zajmującym się bezpieczeństwem nad Wisłą miała w głowie jedno hasło. Euro 2012. Współorganizowana przez Polskę impreza, miała ściągnąć do kraju tłumy kibiców, co samo w sobie jest wyzwaniem. Dodatkowo, był to okres, w którym każde większe skupisko ludzkie postrzegane było jako potencjalny cel dla terrorystów. A strefy kibica, komunikacja miejska zapchana kibicami, czy po prostu ogródki piwne w dni bez rozgrywek, wyglądały jak zaproszenie dla fundamentalistów z ISIS, czy podobnych organizacji.</p>

<p>Dlatego też, w latach poprzedzających Mistrzostwa, polskie służby poczyniły, obok zmian organizacyjnych, szereg zakupów zwiększających ich gotowość do działania w trakcie tak dużej imprezy.</p>

<p>Tak właśnie trafiło do nas 6 urządzeń LRAD, zakup których może być tematem oddzielnego artykułu. Zresztą był, i to niejednego, bo <a href="https://www.nik.gov.pl/najnowsze-informacje-o-wynikach-kontroli/nik-o-zakupie-lrad-w-policji.html" target="_blank">jak zbadała Najwyższa Izba Kontroli</a>, pełno było tam niejasności i zwykłej niegospodarności.</p>

<p>Bowiem po pierwsze, Policja sama zawyżyła cenę urządzeń. Po drugie- kupiła je bez prowadzenia żadnych testów, a jedynie zadowalając się prezentacją przeprowadzoną przez dystrybutora. Zaś same warunki przetargu były tak napisane, że z góry było wiadomo, kto ma go wygrać.</p>

<p>Poza tym sprzęt został dostarczony niekompletny- miał za krótkie kable zasilające, brakowało pokrowców. A w związku z tym, że wszyscy odbiorcy urządzeń, poza Garnizonem Stołecznym, nie zgłosili zastrzeżeń - braki Policja musiała uzupełniać na swój koszt.</p>

<p>No i wreszcie, LRAD, mimo opisów jego skuteczności jako środka przymusu, nie mógł być użyty w takim charakterze. Zatem Policja, za kilkaset tysięcy, kupiła sześć dobrej jakości głośników.</p>

<p><img src="/img/posts/2026-02-03/lrad3.jpg" /></p>

<h2 id="dlaczego-lrad-jest-nielegalny">Dlaczego LRAD jest nielegalny?</h2>

<p>I tu dochodzimy do klu całej afery. Bowiem w wielu wzmiankach o LRAD, jego nielegalność jest używana do podkreślania niszczycielskiej mocy tej broni. Można odnieść wrażenie, że zakaz jego użycia wynika z przesłanek humanitarnych - po prostu nikt nie zasłużył na tak okrutny los, jak słuchanie wydawanego przez niego dźwięku.</p>

<p>Dlatego warto zadać sobie pytanie, dlaczego właściwie użycie LRAD jest nielegalne? Wbrew pozorom, nie wynika to z Konwencji Genewskiej, ani EKPC. O nie, rzeczywistość jest dużo bardziej prozaiczna.</p>

<p>Policja, jak każda instytucja państwowa, działa w granicach prawa. Oznacza to, że może podejmować jedynie takie działania, przy użyciu takich środków, na jakie zezwolą jej przepisy.</p>

<p>W 2010 roku, użycie środków przymusu bezpośredniego, regulowane było przez<a href="https://isap.sejm.gov.pl/isap.nsf/download.xsp/WDU19900700410/O/D19900410.pdf" target="_blank"> Rozporządzenie Rady Ministrów z 17 września 1990</a>. Był to akt prawny, opisujący dostępne dla policjantów środki przymusu, oraz procedury ich użycia. I, jak nietrudno przewidzieć, nikt nie wpisał tam środków do obezwładniania energią fali akustycznej.</p>

<p>Na tym jednak historia się nie kończy. Bowiem w 2012r., wyrokiem o sygnaturze<a href="https://sip.lex.pl/akty-prawne/dzu-dziennik-ustaw/wyrok-trybunalu-konstytucyjnego-sygn-akt-k-10-11-17886955" target="_blank">K 10/11</a>, Trybunał Konstytucyjny uchylił wspomniane rozporządzenie. Uznano bowiem, że kwestia użycia siły wobec obywateli jest sprawą tak newralgiczną, że należy ją uregulować ustawą.</p>

<p>Dlatego też rząd rozpoczął prace i 24 maja 2013 roku przegłosowano <a href="https://sip.lex.pl/akty-prawne/dzu-dziennik-ustaw/srodki-przymusu-bezposredniego-i-bron-palna-17996936/art-12" target="_blank">nową ustawę o środkach przymusu bezpośredniego i broni palnej</a>.</p>

<p>I nie zgadniecie. Nikt nie pamiętał, albo i nawet nie planował, żeby wpisać w niej LRADy, które do tej pory już wrosły w krajobraz demonstracji, służąc jako głośniki - bowiem część panelu, służąca do użycia ich w charakterze środka przymusu, została wymontowana.</p>

<p>Tylko, jak widać, z pewną regularnością, ktoś sobie o ich pełnych możliwościach przypomina. I postanawia wykorzystać to w <a href="https://wiadomosci.wp.pl/posel-osmieszyl-swoich-kolegow-straszyl-nielegalna-bronia-pis-u-zapomnial-kto-ja-kupil-6197848030930561a" target="_blank">aktualnej grze politycznej</a>.</p>]]></content><author><name>Niedźwiedź</name></author><category term="policja" /><category term="policja" /><category term="mity" /><category term="LRAD" /><category term="spb" /><summary type="html"><![CDATA[Muszę powiedzieć, że niedawno zakręciła mi się łezka w oku. Przy okazji policyjnego zabezpieczenia Marszu Niepodległości, po raz kolejny pojawiły się oskarżenia o policyjne prowokacje.]]></summary></entry><entry><title type="html">O dyskryminacji pozytywnej</title><link href="https://niedzwiedz.blog/ogolne/2026/01/04/o-dyskryminacji.html" rel="alternate" type="text/html" title="O dyskryminacji pozytywnej" /><published>2026-01-04T07:48:53+00:00</published><updated>2026-01-04T07:48:53+00:00</updated><id>https://niedzwiedz.blog/ogolne/2026/01/04/o-dyskryminacji</id><content type="html" xml:base="https://niedzwiedz.blog/ogolne/2026/01/04/o-dyskryminacji.html"><![CDATA[<p>Sporo szumu zrobiła ostatnio wypowiedź Katarzyny Kotuli o dyskryminacji pozytywnej. Przypomnijmy- w programie Bogdana Rymanowskiego w Radiu Zet, ministra ds. Równości, zapytana przez gospodarza o dodatkowe punkty za płeć przy rekrutacji do projektów naukowych, czy kursów programowania, odparła, że mamy do czynienia z “dyskryminacją pozytywną”. No i się zaczęło.</p>

<p>Media, zwłaszcza po prawicowej stronie naszych publicznych barykad zaczęły rozpisywać się o <a href="https://www.facebook.com/watch/?v=897468246357085" target="_blank">fikołku logicznym</a> - bo przecież dyskryminacja jest zawsze zła. Bo przecież lewica zdawała się walczyć o równość, <a href="https://wpolsce24.tv/publicystyka/kotula-za-pozytywna-dyskryminacja,58856" target="_blank">aż tu nagle popiera dyskryminację</a>.</p>

<p>Mówiono o hipokryzji- dyskryminacja jest zła, ale tylko wtedy, gdy jej ofiarą padają kobiety. <a href="https://wpolsce24.tv/publicystyka/kotula-za-pozytywna-dyskryminacja,58856" target="_blank">Kiedy dyskryminuje się mężczyzn, to jest ‘pozytywna’</a>.</p>

<p>Muszę powiedzieć, że trochę złapałem się za głowę, a trochę roześmiałem. Tak to z reguły bywa, kiedy konserwatyści ze zdumieniem odkrywają zjawiska dobrze opisane od kilkudziesięciu lat.</p>

<p>Bowiem wystarczy chwila wyszukiwania, by zauważyć, że ‘dyskryminacja pozytywna’ jest terminem używanym w naukach społecznych w miarę powszechnie. Można o niej poczytać na <a href="https://www.facebook.com/schmorgpl/posts/jak-przewidywali%C5%9Bmy-dyskryminacja-pozytywna-na-sta%C5%82e-wchodzi-do-s%C5%82ownika-r%C3%B3wno%C5%9Bc/867531826204495/" target="_blank">Wikipedii</a>, w <a href="https://pro.rp.pl/kadry-i-place/art35633811-pozytywna-dyskryminacja-jest-dopuszczalna-a-czasem-wskazana" target="_blank">prasie</a>, czy <a href="https://prawo.ug.edu.pl/sites/default/files/_nodes/strona-pia/33461/files/35rytel.pdf" target="_blank">tekstach naukowych</a>.</p>

<p>Owszem, kiedy pada hasło dyskryminacja, z reguły myślimy o czymś złym. Kobiety, które jeszcze 100 lat temu w wielu państwach nie miały prawa głosu, albo choćby założenia konta bankowego. Segregacja rasowa w USA, w ramach której czarni np. nie mieli prawa zajmować części miejsc w autobusach. Albo czasy niemieckiej okupacji, gdy na drzwiach kawiarni, tramwaju czy ławce w parku zobaczyć można było tabliczkę z napisem “Nur für Deutsche”.</p>

<p><img src="/img/posts/2026-01-04/rosa.jpg" /></p>

<p>Nawet słownik języka polskiego, w definicji dyskryminacji podaje jedynie to negatywne znaczenie. Dopiero zakładka <code class="language-plaintext highlighter-rouge">etymologia</code> kieruje nas do łacińskiego <code class="language-plaintext highlighter-rouge">discriminatio</code>- czyli rozróżniania. Czyli wyodrębniania jakiejś grupy.</p>

<p>A przecież przykładów pozytywnej dyskryminacji jest wokół nas cała masa. Dziecko wychowywane przez samotnego rodzica dostanie dodatkowe punkty przy naborze do przedszkola, podobnie - dzieciaki z rodzin wielodzietnych.</p>

<p>W niektórych miastach osoby bezrobotne mają prawo do bezpłatnych przejazdów komunikacją miejską. Osoby z niepełnosprawnościami mają dostęp do dedykowanych miejsc parkingowych a pracodawcom oferowane są dodatkowe benefity za ich zatrudnianie.
Można by tak wymieniać całkiem długo, ale myślę, że każdy może w najbliższym otoczeniu znaleźć przynajmniej kilka takich przykładów.</p>

<p>Dlaczego zatem zaczyna nam to przeszkadzać dopiero kiedy kobieta konkuruje z mężczyznami o dostęp do zajęć prestiżowych czy lepiej płatnych?</p>

<p>To pytanie do adeptów historii z zacięciem feministycznym. Ja, na koniec, chciałbym wspomnieć o wspomnianym już zarzucie. Skoro lewica ma na sztandarach równość, a tu nagle propaguje dyskryminację- pal już licho, czy pozytywną, czy negatywną. Jak to obronić?</p>

<p><img src="/img/posts/2026-01-04/Equality-Equity-Reality.jpg" /></p>

<p>Myślę, że dość prosto. Wystarczy przestać utożsamiać równość z “każdemu tak samo”, a zacząć z “każdemu takie same szanse”.</p>

<p>Wyobraźcie sobie, że mieszkacie w niewielkim miasteczku. W promieniu 100km jest jedno kino, znajdujące się na trzecim piętrze miejscowego domu kultury. Czy każdy mieszkaniec ma równy dostęp do oglądania filmów na dużej sali?</p>

<p>W końcu nikt nie jest dyskryminowany- każdy tak samo może przyjść, zapłacić dwie dyszki, wejść wąską klatką schodową i patrzeć na wyczyny Toma Hardy’ego, czy Jennifer Lawrence.</p>

<p>Ale czy będzie to taki sam wysiłek dla wysportowanego maturzysty, rzutkiego przedsiębiorcy, emerytki na wózku i matki szóstki dzieci?</p>

<p>A co jeśli starszą panią wpuścimy wejściem dla personelu, gdzie jest dostęp do windy towarowej<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup> a Matce-Polce sześć biletów raz w miesiącu zafunduje urząd miasta. Czy wtedy będzie równiej, czy nierówniej?</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>Na potrzeby przykładu pomińmy rozważania o dostosowywaniu architektury <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Niedźwiedź</name></author><category term="ogolne" /><category term="felieton" /><category term="ogolne" /><category term="lewica" /><category term="spoleczenstwo" /><category term="dyskryminacja" /><summary type="html"><![CDATA[Sporo szumu zrobiła ostatnio wypowiedź Katarzyny Kotuli o dyskryminacji pozytywnej. Przypomnijmy- w programie Bogdana Rymanowskiego w Radiu Zet, ministra ds. Równości, zapytana przez gospodarza o dodatkowe punkty za płeć przy rekrutacji do projektów naukowych, czy kursów programowania, odparła, że mamy do czynienia z “dyskryminacją pozytywną”. No i się zaczęło.]]></summary></entry><entry><title type="html">Jak przestałem być dziwnym koniem</title><link href="https://niedzwiedz.blog/nalog/2025/12/10/jak-przestalem-byc-dziwnym-koniem.html" rel="alternate" type="text/html" title="Jak przestałem być dziwnym koniem" /><published>2025-12-10T07:48:53+00:00</published><updated>2025-12-10T07:48:53+00:00</updated><id>https://niedzwiedz.blog/nalog/2025/12/10/jak-przestalem-byc-dziwnym-koniem</id><content type="html" xml:base="https://niedzwiedz.blog/nalog/2025/12/10/jak-przestalem-byc-dziwnym-koniem.html"><![CDATA[<p>Czytam<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup> ostatnio znakomitą książkę <a href="https://lubimyczytac.pl/ksiazka/5187209/atypowa-glowa-moje-zycie-w-spektrum-rozmowy-o-neuroroznorodnosci" target="_blank">Katarzyny Kachel “Atypowa Głowa”</a>. Zbierałem się do niej jak pies do jeża, czując, że będzie to trudna lektura. I nie pomyliłem się, bo przez pierwsze dwa rozdziały praktycznie non-stop miałem łzy w oczach. Tak bardzo niektóre momenty były o mnie.</p>

<p>Diagnoza ADHD przyszła do mnie zupełnie znienacka. Jakoś tak przy okazji. A w zasadzie nie tyle przyszła, co przychodziła, bo był to proces który trwał jakiś czas.</p>

<p>Zaczęło się chyba od tego, że Małgorzata Halber wrzuciła w social media post o swojej diagnozie. Z autorką tą miałem taką przygodę, że jej książka <a href="https://www.google.com/url?q=https://lubimyczytac.pl/ksiazka/4863416/najgorszy-czlowiek-na-swiecie&amp;sa=D&amp;source=docs&amp;ust=1765219814392639&amp;usg=AOvVaw0FVZCB4B6vT2t3CfUWoHmQ" target="_blank">‘Najgorszy człowiek na świecie”</a> trafiła do mnie, kiedy byłem w czynnym nałogu.</p>

<p>Czytałem o jej zmaganiach z alkoholem i emocjach, które w szpony uzależnienia ją pchało. Co chwila mruczałem pod nosem ‘kurde, przecież to zupełnie jak u mnie’. Tylko nie przychodziło mi wtedy do głowy, że ja też mam problem z alkoholem- jakoś ten element zupełnie nie pasował.</p>

<p>Sytuacja powtórzyła się, kiedy autorka przyznała się, że lata po rozpoczęciu trzeźwienia, zdiagnozowano u niej ADHD. I że prawie jedna trzecia osób z tym zaburzeniem boryka się z uzależnieniem.</p>

<p>Znowu, czytałem listę objawów, mruczałem pod nosem ‘no niesamowite…’, ale do łba mi nie przyszło, że ja też. Ja? Przecież jestem całkiem normalny, skończę odwyk, wezmę się w garść i będzie ok. Potem, na podobne wpisy u znajomych trafiałem jeszcze kilka razy, ale nadal nic mi nie świtało.</p>

<p>Innym razem, podczas porannego spaceru z psem, staliśmy z sąsiadami, i czekając aż nasze psy wymienią swoje plotki, rozmawialiśmy o studiach. Kiedy wymieniłem wszystkie kierunki, które zacząłem, nie kończąc żadnego, obecna w naszym gronie psycholożka stwierdziła “ej, a ty nie masz ADHD?”.</p>

<p>Zaśmiałem się tylko, bo wydało mi się to absurdalne. Ja po prostu jestem tak chaotyczny, że w okolicy drugiego roku mi się nudziło i traciłem jakąkolwiek motywację.
Dopiero na którejś sesji z terapeutką, opowiadałem o codziennych frustracjach. Bo tak to właśnie nazywałem- muszę być strasznie życiowo sfrustrowany, skoro tak wiele rzeczy mnie na co dzień wkurza.</p>

<p>Jeśli ktoś za wolno idzie przede mną, albo jeśli muszę poczekać na przystanku na autobus. I nie, nie chodzi o to, że autobus się spóźnia. Bywam wkurwiony, bo ja już przyszedłem na przystanek a autobusu nie ma-i to, że nawet nie patrzyłem na rozkład, kiedy powinien byc, nic tu nie zmieniało.</p>

<p>Opowieśc tą przerwałem w pół zdania, bo w mojej głowie zaświtała myśl- a może to nie frustracja? A może po prostu nie jestem stworzony do czekania?</p>

<p>Im dłużej o tym myślałem, tym więcej rzeczy pasowało. Sprawdziłem jeszcze raz listę typowych objawów i co chwila zastanawiałem się, dlaczego dopiero teraz na to wpadłem.</p>

<p>Na przykład- częste popełnianie błędów z nieuwagi. Nie zliczę ile razy musiałem poprawiac jakieś zadanie w pracy, bo skoncentrowałem się na pierwszej linijce opisu, a detali, czy wskazówek zawartych dalej nie zauważyłem.</p>

<p>Problemy z organizacją pracy i odkładanie wszystkiego na ostatnią chwilę- tak, zawsze, od kiedy pamiętam. Nauka w noc przed egzaminem, radosne pisanie skrawków kodu przez dwa tygodnie, by dzień przed deadlinem, w stresie, wyrzucać z siebie 100 linii w kwadrans? Norma.</p>

<p>Hiperfokusy? Kiedy zacząłem się wspinać, przez miesiąc przeczytałem kilkanaście książek o historii dyscypliny, analizowałem modele sprzętu i wirtualnie zwiedzałem rejony na całym świecie.</p>

<p>Kiedyś kolega nieopatrznie pokazał mi figurki do Bolt Action- gry bitewnej w realiach II Wojny Światowej. Nie, nigdy w to nie zagrałem, ale przez dwa tygodnie zdążyłem obejrzeć kilkadziesiąt rozgrywek i prezentacji, charakterystyki jednostek, przeczytać trzy książki  i zobaczy kilkanaście dokumentów o działaniach brytyjskiej 8 Armii w Afryce.</p>

<p>Gubienie rzeczy? Perfekcjonizm? Nawyki ruchowe? Zaczynanie miliona zadań i niekończenie żadnego? Wszystko to doskonale mnie opisywało. Jak ja mogłem tego wcześniej nie zauważać?</p>

<p>No dobrze, ale sama autodiagnoza, jak pewna by nie była, zawsze będzie obarczona możliwością poważnych błędów poznawczych. Moja terapeutka, podobnie jak lekarka z ośrodka, stwierdziła, że na ADHD się nie zna, więc nie pomoże. Musiałem poszukać pomocy na zewnątrz.</p>

<p>I tak właśnie wylądowałem na kozetce u lekarki psychiatrii, która specjalizuje się w ADHD. Wyobrażałem sobie, że przejdziemy przez cały formularz <a href="https://https://www.google.com/url?q=https://www.studocu.com/pl/document/uniwersytet-wyzsza-szkola-bankowa-merito-lodz/psychologia/test-diva-5-przesiewowy-test-do-diagnozy-adhd-jezyk-polski/99796966&amp;sa=D&amp;source=docs&amp;ust=1765219814393076&amp;usg=AOvVaw1unffXF09kPHFIIRsrzzG1" target="_blank">DIVA-5</a>, albo któreś inne z narzędzi diagnostycznych.
Ale po prostu zacząłem opowiadać historię swojego życia. Lekarka co jakiś czas zadawała jakieś pytanie, na które zaczynałem rzucać setki przykładów z życia, co i rusz uciekając w kolejne dygresje.</p>

<p>W końcu, z miną “co tu diagnozować, jak tu gołym okiem widać”, zapytała czego od niej oczekuję.</p>

<p>Muszę przyznać, że byłem trochę zaskoczony tym pytaniem. Nie sądziłem, że zabrnę aż tak daleko. Więc czego tak naprawdę chciałem?</p>

<p>Chciałem nauczyć się normalnie żyć.Nauczyć się radzić sobie z całym tym chaosem i tym, jak funkcjonuje mój mózg. Ale to nie takie łatwe.</p>

<p>Owszem, są leki, ale one nie leczą ADHD, a jedynie maskują objawy. ADHD to zaburzenie rozwojowe. Niektórzy rodzą się wysocy, inni mają znakomitą mobilność i rozciąganie nie sprawia im problemów. A ja się urodziłem z mózgiem, który działa tak a nie inaczej.</p>

<p>I tu medycyna niewiele pomoże. Można próbować terapii, ale też ukierunkowanej na to, żeby nauczyć się żyć zgodnie ze swoją specyfiką.</p>

<p>Więc czego ja naprawdę chciałem? Tak naprawdę, tamtego dnia najważniejsze było dla mnie to, że wreszcie ktoś znalazł nazwę dla tak wielu rzeczy, z którymi męczyłem się całe życie.</p>

<p>Z wieloma nauczyłem sobie jakoś radzić. Telefon zawszę noszę w prawej kieszeni spodni-wtedy wiem, że go nie zapomniałem<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup>, w trakcie zebrań on-line gram w szachy, żeby nie przestac słuchac.</p>

<p>Wiele stanowiło takie dziwactwa, zrzucane po prostu na to, że jestem lekko rozkojarzony cały czas. Na przykład, we wspomnianej książce, jeden z bohaterów stwierdza, że nie ma pamięci do twarzy.</p>

<p>Mam tak samo. I nie chodzi o to, że nie pamiętam jak ktoś wygląda. Po prostu widzę jakąś twarz i ona mi się kojarzy z kilkoma osobami- na przykład, nigdy nie umiem odróżnić Ala Pacino i Roberta de Niro<sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup>.</p>

<p>Wreszcie, są takie, które mnie niszczyły, powodując kolejne frustracje i kryzysy. Perfekcjonizm, zwlekanie na ostatni moment, ciągła niepewność co do swojej wartości. Pewnie znalazłoby się tego więcej, a i na odwyku wiele razy te cechy omawiałem, nie wiedząc o ich przyczynie.</p>

<p>Ktoś kiedyś ładnie powiedział, że jednym z najważniejszych elementów diagnozy jest spokój jaki daje. Całe życie czujesz się gorszy- inne konie są kare, gniade a ty masz jakieś dziwaczne paski. Aż wreszcie ktoś cię diagnozuje, i okazuje się, że jesteś zebrą. To normalne, nie jesteś jedyny.</p>

<p>Sama diagnoza niewiele zmienia, nadal jestem tą samą osobą, nadal mam podobne problemy. Ale nagle przestałem się zadręczać, wyrzucać sobie “co z tobą nie tak”, “dlaczego jesteś taki pojebany”. Wreszcie dostałem chwilę spokoju.</p>

<p>I nazwę. A to ważne, bo dzięki temu, że umiem ten problem nazwać, umiem szukać rozwiązań. Czytam kolejne książki, słucham podkastów, rozmawiam ze znajomymi. I odkrywam, jak wiele osób mierzy się z podobnymi problemami.</p>

<p>Ale póki nie umiałem ich nazwać, nie umieliśmy o nich rozmawiać, i byliśmy z tym sami.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>A w zasadzie słucham, bo niedawno przekonałem się do audiobooków. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2">
      <p>Ostatnio, wychodząc z remizy po alarmie, miałem coś dużego w rękach i ciężko było sięgnąć do spodni, więc włożyłem go do wewnętrznej kieszeni kurtki. Po 5 minutach stwierdziłem, że nie mam go przy sobie i dopiero po przeszukaniu wozu, szatni i garażu wpadłem na to, że może by w innej kieszeni. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3">
      <p>Co sprawia, że oglądanie “Gorączki”, mimo że to fantastyczny film, jest dla mnie trudnym doświadczeniem. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Niedźwiedź</name></author><category term="nalog" /><category term="felieton" /><category term="ogolne" /><category term="nalog" /><category term="adhd" /><category term="diagnoza" /><summary type="html"><![CDATA[Czytam1 ostatnio znakomitą książkę Katarzyny Kachel “Atypowa Głowa”. Zbierałem się do niej jak pies do jeża, czując, że będzie to trudna lektura. I nie pomyliłem się, bo przez pierwsze dwa rozdziały praktycznie non-stop miałem łzy w oczach. Tak bardzo niektóre momenty były o mnie. A w zasadzie słucham, bo niedawno przekonałem się do audiobooków. &#8617;]]></summary></entry><entry><title type="html">Dataclassy w Pythonie</title><link href="https://niedzwiedz.blog/it/2025/08/28/dataclass.html" rel="alternate" type="text/html" title="Dataclassy w Pythonie" /><published>2025-08-28T07:48:53+00:00</published><updated>2025-08-28T07:48:53+00:00</updated><id>https://niedzwiedz.blog/it/2025/08/28/dataclass</id><content type="html" xml:base="https://niedzwiedz.blog/it/2025/08/28/dataclass.html"><![CDATA[<p>Jakiś czas temu, w ramach zadania rekrutacyjnego, miałem zaimplementować prosty system bankowy. Zadanie było podzielone na etapy i wykonywane na żywo, w ograniczonym czasie.
Po poprawnym napisaniu obsługi dodawania kont, wpłacania i wypłacania z nich pieniędzy, otrzymałem kolejne polecenie.</p>

<p>Następną funkcjonalnością miały być przelewy zlecone. Miałem stworzyć kolejkę, do której użytkownik będzie mógł wrzucić zdefiniowany przelew - podając kwotę, konta wysyłającego i adresata, oraz timestamp, w jakim przelew ma być wykonany.</p>

<p>W prawym rogu ekranu widziałem stoper, który bezlitośnie odliczał minuty pozostałe do końca. Postanowiłem więc oszczędzić sobie czasu i, zamiast definiować jakąś strukturę danych, przechowywać dane tych operacji w zwykłej krotce (<em>tuple</em>). I to był poważny błąd.</p>

<p>Nie zliczę ile razy w ciągu kolejnego kwadransa zadawałem sobie pytania “czy timestamp jest na pierwszym, czy ostatnim miejscu?”, albo “najpierw jest kwota czy id odbiorcy?”. Finalnie, straciłem pewnie więcej czasu, tyle że podzielonego na mniejsze, za to wypełnione wkurwieniem, odcinki.</p>

<p>Co mogłem zrobić, żeby tego uniknąć? Kiedy <a href="https://niedzwiedz.blog/it/2025/03/06/protokoly-w-pythonie.html" target="_blank">pisałem o protokołach</a>, wspominałem o obiektach służących głównie do przechowywania danych. I o jednym z nich - <code class="language-plaintext highlighter-rouge">dataclass</code> będzie traktował ten wpis.</p>

<p>Zacznijmy jednak od definicji problemu. Jedną jego stronę już znamy- użycie krotki jest rozwiązaniem szybkim, ale wysoce niesatysfakcjonującym. Można spróbować zamienić krotkę na słownik. Wtedy nie będę musiał pamiętać o kolejności, mogę sobie ponazywać pola jak chcę i się do nich odwoływać. Zatem zamiast tego:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sender</span> <span class="o">=</span> <span class="mi">121</span>
<span class="n">receiver</span> <span class="o">=</span> <span class="mi">144</span>
<span class="n">amount</span> <span class="o">=</span> <span class="mi">1000</span>
<span class="n">timestamp</span> <span class="o">=</span> <span class="mi">11</span>

<span class="n">delayed_transfer_tuple</span> <span class="o">=</span> <span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="n">receiver</span><span class="p">,</span> <span class="n">amount</span><span class="p">,</span> <span class="n">timestamp</span><span class="p">)</span>
</code></pre></div></div>
<p>Miałbym to:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">delayed_transfer_dict</span> <span class="o">=</span> <span class="p">{</span>
    <span class="sh">"</span><span class="s">sender</span><span class="sh">"</span><span class="p">:</span> <span class="n">sender</span><span class="p">,</span>
    <span class="sh">"</span><span class="s">receiver</span><span class="sh">"</span><span class="p">:</span> <span class="n">receiver</span><span class="p">,</span>
    <span class="sh">"</span><span class="s">amount</span><span class="sh">"</span><span class="p">:</span> <span class="n">amount</span><span class="p">,</span>
    <span class="sh">"</span><span class="s">timestamp</span><span class="sh">"</span><span class="p">:</span> <span class="n">timestamp</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Czy jest to lepsze? Nadal muszę pamiętać, czy kwota to <code class="language-plaintext highlighter-rouge">ammount</code> czy <code class="language-plaintext highlighter-rouge">sum</code>, IDE nie podpowie
mi jaka jest nazwa, a nazwy pól muszę podawać używając gołych stringów. Co przy pobieraniu może wywołać błędy, ale przy operacjach przypisania może pozostać niezauważone. Jak w poniższym przykładzie.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">delayed_transfer_dict</span><span class="p">[</span><span class="sh">"</span><span class="s">amount</span><span class="sh">"</span><span class="p">]</span> <span class="o">=</span> <span class="mi">11</span>
</code></pre></div></div>
<p>Suma pozostanie niezmieniona, za to słownik wzbogaci się o kolejną parę klucz-wartość, a ja będę się głowił 
dlaczego przypisanie się nie powiodło<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>.</p>

<p>Z drugiej strony, definiowanie całej klasy, wydaje się nieco nadmiarowe, choćby ze względu na ilość kodu, którą trzeba wygenerować. Zacznijmy od rzeczy najprostszych:</p>

<div id="code-example-1" class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">DelayedTransfer</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">sender</span><span class="p">,</span> <span class="n">receiver</span><span class="p">,</span> <span class="n">amount</span><span class="p">,</span> <span class="n">timestamp</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="n">sender</span> <span class="o">=</span> <span class="n">sender</span>
        <span class="n">self</span><span class="p">.</span><span class="n">receiver</span> <span class="o">=</span> <span class="n">receiver</span>
        <span class="n">self</span><span class="p">.</span><span class="n">amount</span> <span class="o">=</span> <span class="n">amount</span>
        <span class="n">self</span><span class="p">.</span><span class="n">timestamp</span> <span class="o">=</span> <span class="n">timestamp</span>

<span class="n">transfer</span> <span class="o">=</span> <span class="nc">DelayedTransfer</span><span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="n">receiver</span><span class="p">,</span> <span class="n">ammount</span><span class="p">,</span> <span class="n">timestamp</span><span class="p">)</span>
</code></pre></div></div>

<p>Niby niewiele, ale każdą z wartości już trzeba było wymienić trzykrotnie. Możliwe jednak, że będziemy  potrzebowali tego kodu więcej. Wyobraźcie sobie choćby sprawdzenie, czy dwa przelewy są identyczne. W krotce dostajemy to za darmo. W przypadku klasy, niestety już nie:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">delayed_transfer_tuple</span> <span class="o">=</span> <span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="n">receiver</span><span class="p">,</span> <span class="n">amount</span><span class="p">,</span> <span class="n">timestamp</span><span class="p">)</span>
<span class="n">delayed_transfer_tuple_2</span> <span class="o">=</span> <span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="n">receiver</span><span class="p">,</span> <span class="n">amount</span><span class="p">,</span> <span class="n">timestamp</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="n">delayed_transfer_tuple</span> <span class="o">==</span> <span class="n">delayed_transfer_tuple_2</span><span class="p">)</span> <span class="c1"># True
</span>
<span class="n">transfer</span> <span class="o">=</span> <span class="nc">DelayedTransfer</span><span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="n">receiver</span><span class="p">,</span> <span class="n">amount</span><span class="p">,</span> <span class="n">timestamp</span><span class="p">)</span>
<span class="n">transfer2</span> <span class="o">=</span> <span class="nc">DelayedTransfer</span><span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="n">receiver</span><span class="p">,</span> <span class="n">amount</span><span class="p">,</span> <span class="n">timestamp</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="n">transfer</span> <span class="o">==</span> <span class="n">transfer2</span><span class="p">)</span>  <span class="c1"># False
</span></code></pre></div></div>

<p>Podobnie z porównaniami, potrzebnymi do sortowania. Metody <code class="language-plaintext highlighter-rouge">__lt__</code>, <code class="language-plaintext highlighter-rouge">__gt__</code> i tak dalej będziemy musieli zaimplementować sami.</p>

<p>Dlatego też powstał dokument <a href="https://peps.python.org/pep-0557/" target="_blank">PEP-557</a>, i w wersji 3.7 Pythona otrzymaliśmy dataclassy- struktury przeznaczone do przechowywania danych, pozwalające na łatwe stworzenie klasy dającej nam powyższe funkcjonalności - właśnie Dataclass.</p>

<p>Dzięki nim, wystarczy poniższa deklaracja:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">DelayedTransfer</span><span class="p">:</span>
    <span class="n">sender</span><span class="p">:</span> <span class="nb">int</span>
    <span class="n">receiver</span><span class="p">:</span> <span class="nb">int</span>
    <span class="n">amount</span><span class="p">:</span> <span class="nb">int</span>
    <span class="n">timestamp</span><span class="p">:</span> <span class="nb">int</span>
</code></pre></div></div>

<p>Abyśmy otrzymali klasę “uzbrojoną” w konstruktor oraz metody <code class="language-plaintext highlighter-rouge">__repr__</code>, <code class="language-plaintext highlighter-rouge">__eq__</code>, i wykorzystywaną przy pattern matchingu krotkę <code class="language-plaintext highlighter-rouge">__match_args__</code> <sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup>
Ale to nie wszystko. O tym, jakie dokładnie metody zostaną wygenerowane, możemy decydować, podając następujące argumenty:</p>

<table>
  <thead>
    <tr>
      <th>Argument</th>
      <th>* Domyślna wartość</th>
      <th>* Generowane metody i pola</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>init</td>
      <td><code class="language-plaintext highlighter-rouge">True</code></td>
      <td><code class="language-plaintext highlighter-rouge">__init__</code></td>
    </tr>
    <tr>
      <td>repr</td>
      <td><code class="language-plaintext highlighter-rouge">True</code></td>
      <td><code class="language-plaintext highlighter-rouge">__repr__</code></td>
    </tr>
    <tr>
      <td>eq</td>
      <td><code class="language-plaintext highlighter-rouge">True</code></td>
      <td><code class="language-plaintext highlighter-rouge">__eq__</code></td>
    </tr>
    <tr>
      <td>order</td>
      <td><code class="language-plaintext highlighter-rouge">False</code></td>
      <td><code class="language-plaintext highlighter-rouge">__lt__</code>, <code class="language-plaintext highlighter-rouge">__gt__</code>, <code class="language-plaintext highlighter-rouge">__le__</code>, <code class="language-plaintext highlighter-rouge">__ge__</code></td>
    </tr>
    <tr>
      <td>unsafe_hash</td>
      <td><code class="language-plaintext highlighter-rouge">False</code></td>
      <td><code class="language-plaintext highlighter-rouge">__hash__</code></td>
    </tr>
    <tr>
      <td>frozen</td>
      <td><code class="language-plaintext highlighter-rouge">False</code></td>
      <td>brak</td>
    </tr>
    <tr>
      <td>match_args</td>
      <td><code class="language-plaintext highlighter-rouge">True</code></td>
      <td><code class="language-plaintext highlighter-rouge">__match_args__</code></td>
    </tr>
    <tr>
      <td>kw_only</td>
      <td><code class="language-plaintext highlighter-rouge">False</code></td>
      <td>brak</td>
    </tr>
    <tr>
      <td>slots</td>
      <td><code class="language-plaintext highlighter-rouge">False</code></td>
      <td><code class="language-plaintext highlighter-rouge">__slots__</code></td>
    </tr>
  </tbody>
</table>

<p>Oczywiście, metody te są bardzo generyczne. Konstruktor jedynie przypisuje wartości pól. Wygenerowane operatory porównania używają krotki z wartościami pól.
Jednak w znacznej większości przypadków, jest to logika całkowicie wystarczająca.</p>

<p>Większość tych parametrów jest dość oczywista. Warto jednak wspomnieć więcej o kilku. I tak, <code class="language-plaintext highlighter-rouge">frozen</code> sprawia, że nasza klasa staje się niezmienna (<code class="language-plaintext highlighter-rouge">immutable</code>),
więc zachowaniem przypomina krotkę na sterydach a jakakolwiek próba przypisania wartości zakończy się rzuceniem <code class="language-plaintext highlighter-rouge">FrozenInstanceError</code>.</p>

<p><code class="language-plaintext highlighter-rouge">Unsafe hash</code> z kolei wymusza stworzenie funkcji <code class="language-plaintext highlighter-rouge">__hash__</code>, nawet jeśli wartości pól naszej klasy mogą się zmieniać. To dośc wyspecjalizowany przypadek, stosowany głównie
wtedy, gdy definicja klasy zawiera mutowalne wartości, ale programista wie, że logika programu nie pozwoli na ich zmianę. Natomiast w przypadku, gdy parametry <code class="language-plaintext highlighter-rouge">eq</code> i <code class="language-plaintext highlighter-rouge">frozen</code>
 ustawione są na <code class="language-plaintext highlighter-rouge">True</code>, metoda <code class="language-plaintext highlighter-rouge">__hash__</code> wygenerowana zostanie automatycznie.</p>

<p>Stworzona w ten sposób klasa w żaden sposób nie różni się od innych klas. Tak samo, możemy zdefiniować w niej swoje własne metody. Czasem jest to nawet nieodzowne.</p>

<p>Sięgnijcie bowiem pamięcią do wszystkich metod <code class="language-plaintext highlighter-rouge">__init__</code> jakie w życiu napisaliście. Zapewne większość z nich zawiera jedynie proste przypisania, w stylu <code class="language-plaintext highlighter-rouge">self.foo = foo</code>.</p>

<p>Zdarza się jednak, że oczekujemy od konstruktora, wykonania bardziej zawiłej logiki. Wyobraźcie sobie, że modelujemy samochód. Dla uproszczenia, nasze auto będzie określane przez kolor i model silnika. Chcielibyśmy jednak określić, jaki dźwięk wydaje nasz samochód- jeśli jest to elektryk, będzie wydawał z siebie bzyczenie,
jeśli zaś diesel albo benzyniak- będzie warczał.</p>

<p>Możemy oczywiście ten dźwięk podać jako kolejny argument dla konstruktora, ale to złe rozwiązanie. Po pierwsze, dopuszczamy pomieszanie dźwięków, a nie chcemy żeby nasze TDI wydawało z siebie brzęczenie komara, zamiast prawdziwie męskich pomruków.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">Car</span><span class="p">:</span>
    <span class="n">engine</span><span class="p">:</span> <span class="nb">str</span>
    <span class="n">color</span><span class="p">:</span> <span class="nb">str</span>
    <span class="n">sound</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="bp">None</span>
</code></pre></div></div>

<p>Dodatkowo, przy każdej instancjalizacji klasy, programista musi zadbać o podanie dodatkowego argumentu, w dodatku zgodnego z dokumentacją.</p>

<p>Rozwiązania są dwa- albo zaszyjemy tę logikę w metodzie z dekoratorem <code class="language-plaintext highlighter-rouge">property</code>, i za każdym razem będziemy
wyznaczać ten dźwięk na nowo, albo użyjemy <code class="language-plaintext highlighter-rouge">__post_init__</code>.</p>

<p>Jest to specjalna metoda, która zostaje wywołana na końcu automatycznie wygenerowanego konstruktora, i pozwala na dopisanie właśnie takiej logiki. Zatem nasza klasa może wyglądać tak:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">Car</span><span class="p">:</span>
    <span class="n">engine</span><span class="p">:</span> <span class="nb">str</span>
    <span class="n">color</span><span class="p">:</span> <span class="nb">str</span>
    
    <span class="k">def</span> <span class="nf">__post_init__</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">self</span><span class="p">.</span><span class="n">engine</span><span class="p">.</span><span class="nf">startswith</span><span class="p">(</span><span class="sh">'</span><span class="s">EL</span><span class="sh">'</span><span class="p">):</span>
            <span class="n">self</span><span class="p">.</span><span class="n">sound</span> <span class="o">=</span> <span class="sh">'</span><span class="s">Wzium</span><span class="sh">'</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">self</span><span class="p">.</span><span class="n">sound</span> <span class="o">=</span> <span class="sh">'</span><span class="s">Brum</span><span class="sh">'</span>
</code></pre></div></div>

<p>Dzięki czemu, nie musimy się już więcej kłopotać dźwiękiem (przynajmniej dopóki coś nie zacznie stukać w nadkolu):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>In [22]: a= Car('Red', 'EL-123')

In [23]: a.sound
Out[23]: 'Wzium'

In [24]: a= Car('Red', 'TDI-123')

In [25]: a.sound
Out[25]: 'Brum'
</code></pre></div></div>

<p>Ale czy korzyść z dataclass ogranicza się do automatycznego generowania metod? No nie. Dzięki klasie <code class="language-plaintext highlighter-rouge">Field</code> 
zyskujemy kontrolę nad tym, jakie wartości atrybutów są dopuszczalne itp. Ale o tym będzie w kolejnym wpisie.</p>

<p>Na koniec jednak muszę dodać jedną ciekawostkę. <a href="https://peps.python.org/pep-0484/#pep-development-process" target="_blank">PEP-484</a>, a więc dokument wprowadzający <a href="https://niedzwiedz.blog/it/2025/02/01/typowanie-w-pythonie.html" target="_blank">adnotacje typów</a>, zakładał, że zawsze będą one opcjonalne. Co za tym idzie, ich obecność, albo nie, nie powinna w żadnym wypadku zmieniać zachowania interpretera w runtime:</p>

<blockquote>
  <p>It should also be emphasized that Python will remain a dynamically typed language, and the authors have no desire to ever make type hints mandatory, even by convention.</p>
</blockquote>

<p>Dataclassy jednak są przypadkiem, kiedy adnotacje zmieniają zachowanie. Weźmy taki przyład, zaczerpnięty ze znakomitej książki Luciano Ramalho <a href="https://www.fluentpython.com" target="_blank">“Fluent Python”</a>.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span>
<span class="nd">@dataclass</span>
<span class="k">class</span> <span class="nc">DemoDataClass</span><span class="p">:</span>
    <span class="n">a</span><span class="p">:</span> <span class="nb">int</span>
    <span class="n">b</span><span class="p">:</span> <span class="nb">float</span> <span class="o">=</span> <span class="mf">1.1</span>
    <span class="n">c</span> <span class="o">=</span> <span class="sh">'</span><span class="s">spam</span><span class="sh">'</span>
</code></pre></div></div>

<p>Jest to prosta klasa z trzema argumentami. Dwa z nich mają adnotacje, a jeden nie. Dwa z nich mają wartości domyślne, a jeden nie. Co zatem dzieje się w runtime?</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;&gt;&gt;</span> <span class="kn">from</span> <span class="n">demo_dc</span> <span class="kn">import</span> <span class="n">DemoDataClass</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">DemoDataClass</span><span class="p">.</span><span class="n">__annotations__</span>
<span class="p">{</span><span class="sh">'</span><span class="s">a</span><span class="sh">'</span><span class="p">:</span> <span class="o">&lt;</span><span class="k">class</span> <span class="err">'</span><span class="nc">int</span><span class="sh">'</span><span class="s">&gt;, </span><span class="sh">'</span><span class="sa">b</span><span class="sh">'</span><span class="s">: &lt;class </span><span class="sh">'</span><span class="nb">float</span><span class="sh">'</span><span class="s">&gt;}
</span><span class="gp">&gt;&gt;&gt;</span> <span class="n">DemoDataClass</span><span class="p">.</span><span class="n">__doc__</span>
<span class="sh">'</span><span class="s">DemoDataClass(a: int, b: float = 1.1)</span><span class="sh">'</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">DemoDataClass</span><span class="p">.</span><span class="n">a</span>
<span class="nc">Traceback </span><span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="sh">"</span><span class="s">&lt;stdin&gt;</span><span class="sh">"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span> <span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
<span class="nb">AttributeError</span><span class="p">:</span> <span class="nb">type</span> <span class="nb">object</span> <span class="sh">'</span><span class="s">DemoDataClass</span><span class="sh">'</span> <span class="n">has</span> <span class="n">no</span> <span class="n">attribute</span> <span class="sh">'</span><span class="s">a</span><span class="sh">'</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">DemoDataClass</span><span class="p">.</span><span class="n">b</span>
<span class="mf">1.1</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">DemoDataClass</span><span class="p">.</span><span class="n">c</span>
<span class="sh">'</span><span class="s">spam</span><span class="sh">'</span>
</code></pre></div></div>

<p>Argumenty <code class="language-plaintext highlighter-rouge">b</code> i <code class="language-plaintext highlighter-rouge">c</code> widoczne są z poziomu klasy. Natomiast pytanie, co zawiera, generowana automatycznie, metoda <code class="language-plaintext highlighter-rouge">__init__</code>?</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>In [16]: inspect.signature(DemoDataClass.__init__)
Out[16]: &lt;Signature (self, a: int, b: float = 1.1) -&gt; None&gt;
</code></pre></div></div>

<p>Jak widać, tylko te atrybuty, które opatrzono adnotacją typu, stają się atrybutami instancji. A zatem, wbrew intencjom autorów, adnotacja typu zmienia zachowanie kodu!</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>O tym, jak prawdopodobny jest to błąd, niech świadczy fakt, że pisząc tego posta, popełniłem go nieświadomie. Dopiero linter uświadomił mi, że chyba mam problem z pisownią. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2">
      <p>Co to takiego <code class="language-plaintext highlighter-rouge">pattern matching</code> napiszę dokładniej w jednym z kolejnych wpisów. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Niedźwiedź</name></author><category term="it" /><category term="python" /><category term="typy" /><category term="dataclass" /><category term="klasy" /><category term="danych" /><category term="struktury" /><category term="obiekty" /><summary type="html"><![CDATA[Jakiś czas temu, w ramach zadania rekrutacyjnego, miałem zaimplementować prosty system bankowy. Zadanie było podzielone na etapy i wykonywane na żywo, w ograniczonym czasie. Po poprawnym napisaniu obsługi dodawania kont, wpłacania i wypłacania z nich pieniędzy, otrzymałem kolejne polecenie.]]></summary></entry><entry><title type="html">O związkach polskiej wsi z dalekim wschodem</title><link href="https://niedzwiedz.blog/nalog/2025/07/02/o-ptakach.html" rel="alternate" type="text/html" title="O związkach polskiej wsi z dalekim wschodem" /><published>2025-07-02T07:48:53+00:00</published><updated>2025-07-02T07:48:53+00:00</updated><id>https://niedzwiedz.blog/nalog/2025/07/02/o-ptakach</id><content type="html" xml:base="https://niedzwiedz.blog/nalog/2025/07/02/o-ptakach.html"><![CDATA[<p>W niewielkiej książeczce “Wprowadzenie do buddyzmu zen” Daisetz Teitaro Suzuki przytacza taką anegdotkę<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>:</p>

<p>Konfucjański poeta Kazankoku udał się do Kwaido, by zostać wprowadzonym w tajniki Zen. Tam jednak usłyszał “W naukach twego mistrza jest wers, który mówi ci wszystko, co powinieneś wiedzieć o Zen. Czyż Konfucjusz nie powiedział «Uczniowie moi, czy myślicie, że ukrywam cokolwiek przed wami? Zaiste, nie mam przed wami nic do ukrycia»”.</p>

<p>Kazankoku próbował odpowiedzieć, ale Kwaido oddalił go, mówiąc tylko “nie, nie”. Uczeń Konfucjusza nie wiedział co począć. Czuł się odrzucony, ale pozostał w szkole Kwaido, mając nadzieję jednak się czegoś nauczyć.</p>

<p>Jakiś czas później, przechadzał się z mistrzem po wzgórzach, pogrążony w rozmowie.  W pewnym momencie Kwaido zapytał “Czy czujesz jak pachną kwiaty?”.</p>

<p>Rzeczywiście. Kwitnące wawrzyny wypełniały powietrze wręcz zniewalającym zapachem. Kazankoku nie mógł ich nie poczuć.</p>

<p>“A zatem nie kłamałem” - odparł mistrz Zen - “niczego przed tobą nie ukrywam”.</p>

<p>Prosta prawda tej opowieści uderzała mnie wielokrotnie w trakcie terapii, kiedy okazywało się, że życie bez alkoholu nie wymaga jakiejś tajemnej wiedzy. Wystarczyło inaczej patrzeć na rzeczywistość i wzmacniać inne nawyki.</p>

<p>Oczywiście, nie oznacza to, że zawsze potrafiłem się do tego zastosować, czy choćby te oczywistości zauważyć. Wszak choroba alkoholowa polega m.in. na ciągłym okłamywaniu się i wmawianiu sobie, że zmiana nie jest możliwa a wszelkie objawy nałogu są całkiem naturalne, a przez to walka z nimi nie ma sensu.</p>

<p>Ale też dlatego, za każdym razem ta anegdota wraca do mnie wywołując wzruszenie i chwilę zadumy.</p>

<p>Jakiś czas temu rozpoczęliśmy ze znajomymi sezon wspinaczkowy. Po całkiem udanym dniu w skałach, schodziliśmy do samochodów, zajęci grą w “zgadnij jakie to zwierzę” z synem jednej z koleżanek.</p>

<p><img src="/img/posts/2025-07-02/q.jpg" class="illustration" /></p>

<p>W pewnym momencie, Mikołaj z Magdą przystanęli i zaczęli nagrywać coś telefonem. Okazało się, że zaciekawił ich śpiew jednego z ptaków. A że nie potrafili go zidentyfikować, wspomogli się sztuczną inteligencją zaklętą w komórkowej aplikacji.</p>

<p>To było takie proste, nie wymagało wielkiej wiedzy, ani szczególnego wysiłku. Wystarczyło zatrzymać się na chwilę i posłuchać.</p>

<p>Od tej pory staram się samemu, choć również z pomocą aplikacji, rozpoznawać, jakie ptaki śpiewają dookoła mnie. A że mieszkamy na wsi, przy wielkiej łące, kończącej się stawem, jest czego słuchać.</p>

<p>I za każdym razem zatrzymuję się w zachwycie. Bowiem śpiew ptaków był dla mnie do tej pory częścią tła. Ścianą dźwięku, zbudowaną z wielu, zlewających się w jedno odgłosów.</p>

<p>A wystarczy na chwilę się zatrzymać, wziąć głęboki oddech, i zacząć wyławiać z nich pojedyncze ćwierknięcia, trele czy okrzyki.</p>

<p>I za każdym razem czuję się niczym Kazankoku, który tak długo był zaabsorbowany sobą, że nie czuł jak pięknie pachną kwiaty.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>Przy przeprowadzce mój egzemplarz gdzieś zaginął, zatem podaję luźne tłumaczenie z wersji angielskiej. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Niedźwiedź</name></author><category term="nalog" /><category term="felieton" /><category term="ogolne" /><category term="nalog" /><category term="medytacja" /><category term="ptaki" /><category term="wies" /><category term="przyroda" /><summary type="html"><![CDATA[W niewielkiej książeczce “Wprowadzenie do buddyzmu zen” Daisetz Teitaro Suzuki przytacza taką anegdotkę1: Przy przeprowadzce mój egzemplarz gdzieś zaginął, zatem podaję luźne tłumaczenie z wersji angielskiej. &#8617;]]></summary></entry><entry><title type="html">Handel narkotykami</title><link href="https://niedzwiedz.blog/policja/2025/03/27/handel-narkotykami.html" rel="alternate" type="text/html" title="Handel narkotykami" /><published>2025-03-27T07:48:53+00:00</published><updated>2025-03-27T07:48:53+00:00</updated><id>https://niedzwiedz.blog/policja/2025/03/27/handel-narkotykami</id><content type="html" xml:base="https://niedzwiedz.blog/policja/2025/03/27/handel-narkotykami.html"><![CDATA[<p>Jakiś czas temu, wspominając że stawianie zarzutów dilerom narkotykowym nie jest tak prostą sprawa, jak mogłoby się wydawać, obiecałem nieco bardziej przybliżyć kwestię walki z dilerami narkotyków.</p>

<p>Polityka narkotykowa to temat rzeka, do którego jeszcze nie raz będe wracał. Niemniej, na początku muszę poczynić jedno ważne zastrzeżenie- nie zajmowałem się tym tematem na co dzień.</p>

<p>O ile często miałem kontakt z osobami uzależnionymi- w końcu rozboje, czy pobicia, którymi się zajmowałem, rzadko popełniano na trzeźwo- to z drugą stroną tej układanki kontakt miałem raczej epizodyczny.</p>

<p>Jak wspominałem, zarówno w dochodzeniówce, jak i w kryminalnym funkcjonowały wydzielone komórki, zajmujące się przestępczością narkotykową.</p>

<p>O ile w WDŚ, funkcjonariusze zajmowali się przede wszystkim obrobieniem “posiadaczy” zwożonych hurtowo przez patrolówkę <sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup> , o tyle operacyjni zajmowali się próbami zwalczania handlarzy. I tu zaczyna się nasza opowieść.</p>

<p>Jeśli znacie trochę Pragę Północ, wiecie że do niedawna, centrum handlu narkotykami były dwie bramy na ul. Brzeskiej. Konkretnie numery 9 i 11. Była to wiedza absolutnie powszechna, zarówno wśród potencjalnych klientów, mieszkańców, dziennikarzy i tropicieli sensacji w internecie.</p>

<p>Powstaje więc oczywiste pytanie- skoro każdy wiedział, to dlaczego Policja nic z tym nie robiła? Czyżby ktoś dostawał w łapę<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup>? Czy jakimś cudem funkcjonariusze nie wiedzieli? A może po prostu się bali?</p>

<p><img src="/img/posts/2025-03-27/praga.jpg" class="illustration" />
<em>
    fot. zbiory własne autora
</em></p>

<p>Nie, na przeszkodzie stało polskie prawo, które (w sumie słusznie) zakłada, że winę oskarżonego należy udowodnić bezspornie, a przynajmniej z dużym prawdopodobieństwem.</p>

<p>Oznacza to, że każdej osobie, której chcemy postawić zarzuty, musimy udowodnić, że brała udział w procederze handlu narkotykami. A to nie jest takie proste.</p>

<p>Bo wiecie, to nie wygląda tak, jak to przedstawiali w szkołach, albo możecie zobaczyć np. “Ślepnąc od świateł” - dzwonisz gdzieś, po czym przyjeżdża do ciebie typek, który w samochodzie ma podręczną aptekę, . To znaczy, czasem to tak wygląda, ale to raczej płotki, albo zaopatrzenie dla specjalnych klientów.</p>

<p>To, jak wygląda prawdziwy handel, na większą skalę, możecie zobaczyć choćby w nieocenionym “The Wire” <sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup>.</p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/WmHG5Pcl2bk?si=P44HjCTPe0Lexhc6&amp;start=152" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""></iframe>

<p>I to właśnie jest pierwszy element problemu. Często, z punktu widzenia prawa, trudno udowodnić, że w danym miejscu ktokolwiek czymkolwiek handluje.</p>

<p>Klient wchodzi do bramy, rozmawia z jedną osobą, kasę daje drugiej, a towar podaje mu trzecia- często np. wyrzucając go przez okno.</p>

<p>Jeśli zatrzymać uczestników procederu, to jeden powie, że witał się z kolegą, drugi- że wziął kasę, bo myślał, że to zwrot długu dla kolegi, a trzeci- znalazł jakieś zawiniątko na klatce schodowej, więc wyrzucił je na podwórko. Gdzie tu jest jakikolwiek handel?</p>

<p>Czasem jednak handlarzom nie chce się bawić w takie środki ostrożności. Ale i nawet wtedy, klient ma kontakt z jednym człowiekiem, któremu płaci, i od którego odbiera towar. Ten z kolei, nie trzyma przy sobie ani towaru, ani pieniędzy - niemal od razu przekazuje je ludziom siedzącym w klatce schodowej.</p>

<p>Nawet jeśli uda się takiemu łebkowi postawić zarzut (bo w końcu do handlu dochodzi tu bezsprzecznie), w ciągu kwadransa od odjazdu Policji, zostanie zastąpiony kolejnym. A ludzie, którzy zarządzają tym biznesem pozostaną nietknięci.</p>

<p>No ale, można powiedzieć, przynajmniej zgarnie się trochę towaru- a to ich przecież zaboli. Może nawet spowoduje, że przez chwilę nie będą handlować.</p>

<p>O słodka naiwności. Owszem, na okolice Brzeskiej, koledzy robili w miarę regularne naloty- właśnie wtedy, gdy można było zabezpieczyć większe ilości towaru. I oczywiście, ładnie to wyglądało w komunikatach prasowych, ale wpływ na sam proceder był nikły.</p>

<p>Kiedyś kolega Łukasz wpadło na jedno z rzeczonych podwórek. Oczywiście, zanim jeszcze skręcił w Brzeską z Ząbkowskiej, został rozpoznany <sup id="fnref:4"><a href="#fn:4" class="footnote" rel="footnote" role="doc-noteref">4</a></sup>. Niemniej, energicznym krokiem udał się do jakiejś skrzynki gazowej, którą otworzył, ujawniając stosik zawiniątek z folii aluminiowej.</p>

<ul>
  <li>Czyje to?
(Cisza)</li>
  <li>No pytam czyje, nie wasze?</li>
  <li>Pierwszy raz w życiu to widzimy - odpowiedziało kilka głosów.</li>
  <li>No to jak nie wasze, to biorę - powiedział, wzywając radiowóz, dzięki któremu protokół sporządzał w blasku policyjnych lamp, które przez dłuższą chwilę wstrzymywały jakikolwiek handel.</li>
</ul>

<p>Innym razem łup był bardziej okazały. Operacyjni uzyskali informację o tym kiedy i gdzie będzie przechowywana dostawa towaru. Przeszukanie lokalu było strzałem w dziesiątkę.</p>

<p>O ile na miejsce jechali tylko swoją sekcją, to gdy zobaczyli ile towaru przyjdzie im zabezpieczyć, wydzwonili do pomocy wszystkich operacyjnych z rejonu- zatrzymane narkotyki miały taką wartość, że zorganizowaliśmy uzbrojony po zęby konwój, by je bezpiecznie przewieźć na komendę.</p>

<p>Dość powiedzieć, że dłuższą chwilę zastanawialiśmy się jak zważyć zatrzymane pakunki do protokołu- wagi, które mieliśmy dostępne, były super dokładne, ale skala kończyła im się w okolicach dwóch kilo, a to dużo za mało jak na potrzeby tamtego dnia.</p>

<p>W końcu pojechaliśmy kolejnym konwojem na pocztę, i tam, przy wadze do paczek, kończyliśmy oględziny. Byłem jednym z kilku “fizycznych” na tej robocie, a susz roślinny jaki nosiłem, miał rynkową wartość dwupokojowego mieszkania.</p>

<p>No to już musiało zaboleć, powiecie. Owszem, ale jaki był efekt? Handel zastopował na jeden dzień, po tygodniu wszystko hulało na nowo.</p>

<p>Natomiast postępowanie, które miało zakończyć się zarzutami posiadania, trwało około 12h - rano na komendę zgłosiła się, niekarana wcześniej, 17-latka, która zeznała że narkotyki znalazła w krzakach nad Wisłą, i z głupoty przyniosła je na swoją klatkę schodową.</p>

<p>Na papier podała, że nie ma pojęcia, do kogo towar należał, nikomu o nim nie mówiła, nikt inny w okolicy o nim nie wiedział. Zawnioskowała o dobrowolne poddanie się karze. I tyle.</p>

<p>Czy to oznacza, że Policja jest bezsilna? No nie. Po prostu, jeśli chce się ugryźć taką grupę przestępczą, trzeba czegoś więcej niż wpadnięcie z krzykiem na podwórko i skucie takich łebków.</p>

<p>Zamiast tego, konieczna jest długa i żmudna praca operacyjna<sup id="fnref:5"><a href="#fn:5" class="footnote" rel="footnote" role="doc-noteref">5</a></sup>, poznawanie schematów, zwyczajów i organizacji takiej grupy.</p>

<p>O skali takiego zbioru informacji, niech świadczy taka historyjka. Do naszej komendy zgłosiło się dwóch mężczyzn, którzy przyjechali na Pragę z towarem, z niewielkiej firmy na południu Polski. Jako że było to pierwsze tak duże zamówienie, po zakończeniu transakcji, postanowili to uczcić.</p>

<p>Kiedy godzinę później, chybotliwym krokiem szli w kierunku hotelu, nawigacja w telefonie poprowadziła ich właśnie Brzeską.</p>

<p>Tam, któraś z czujek rzuciła pod ich adresem kąśliwy komentarz, czego pokrzywdzeni nie chcieli puścić mimo uszu. Po krótkiej wymianie zdań, z bramy wybiegło jeszcze trzech kolegów, i dotkliwie pobili naszych biznesmenów.</p>

<p>Szczęściem w nieszczęściu był fakt, że parzysta strona Brzeskiej była już zajęta nowymi blokami, a to oznaczało, że cała sytuacja, z pewnej odległości, ale jednak została uchwycona przez kamery monitoringu.</p>

<p>Po zabezpieczeniu nagrania, poleciałem do “narkusów”, poprosić o pomoc w dopasowaniu tych kilku zbitków pikseli, jakie miałem na filmie, do konkretnych nazwisk.</p>

<p>W kilka sekund po naciśnięciu “play”, usłyszałem “ten tak się kołysze, że to musi być Maciek, pseudo ‘Makak’. Ten co wybiega z bramy jest gruby i wolny - na niego wołają własnie ‘Gruby`. A ten co go pogania, to musi być ‘Rudy’ - oni zawsze się bujają razem”.<sup id="fnref:6"><a href="#fn:6" class="footnote" rel="footnote" role="doc-noteref">6</a></sup></p>

<p>Po chwili, praktycznie z pamięci dostałem daty urodzenia i adresy zamieszkania delikwentów. Pozostało tylko się odwdzięczyć, i przed wyznaczeniem daty zatrzymania, skonsultować ją z kolegami, którzy mogli chcieć skorzystać z okazji, i przy okazji przeszukać jedno, czy drugie mieszkanie.</p>

<p>Na koniec warto jeszcze wspomnieć o jednym pytaniu. Dlaczego nie można po prostu utrudnić procederu- skierować na miejsce dodatkowych sił, samą swoją obecnością przegonią handlarzy?</p>

<p>Jak to często bywa, zalążek odpowiedzi ukrywa się w samym pytaniu. Skoro mają tych handlarzy przegonić, to pojawia się pytanie- gdzie.</p>

<p>Zapewne proceder pojawi się w najlepsze gdzie indziej. I tam również trzeba będzie skierować dodatkowe siły. I policja będzie się tak bawić w ganianego, a patrole, których nie ma za dużo<sup id="fnref:7"><a href="#fn:7" class="footnote" rel="footnote" role="doc-noteref">7</a></sup>, będą musiały zniknąć z innych miejsc.</p>

<p>Więc, gdy dojdzie do pobicia, albo włamania, niechybnie pojawi się pytanie- dlaczego Policji tam nie było?</p>

<p>Dlatego właśnie, na pierwszy rzut oka, może wydawać się, że Policja nic z handlem narkotykami nie robi. Prawda jest jednak taka, że to “nic”, bardzo często oznacza wytężoną i żmudną pracę, która owoce przynosi dopiero po latach.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>Celował w tym zwłaszcza Wydział Wywiadowczo-Patrolowy KSP. Jego funkcjonariusze są rozliczani głównie za zatrzymania przestępców na gorącym uczynku. Więc jeśli nie chcą dostać opierdolu, to mogą albo liczyć na to, że zauważą jak ktoś popełnia rozbój, czy włamanie (na co szanse są nikłe), albo zatrzymają kogoś z choćby śladowymi ilościami narkotyków (co jest proste i szybkie). To kolejny przykład, kiedy na papierze jakaś polityka wygląda znakomicie, a w życiu wychodzi trochę gorzej- ale o tym innym razem. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2">
      <p>Od razu przepraszam kolegów z referatu narkotykowego za takie insynuacje. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3">
      <p>Który to serial bardzo gorąco polecam. Jakiś czas temu poleciłem go partnerce, i z radością, na nowo obejrzałem wszystkie 5 sezonów, stwierdzając, że nadal wiele sytuacji da się przełożyć jeden do jednego, na problemy polskiej Policji. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4">
      <p>Musicie bowiem wiedzieć dwie rzeczy- po pierwsze, policjantów w kryminalnym jest kilkunastu, więc po paru latach pracy, stali bywalcy komendy, znają ich przynajmniej z twarzy, jeśli nie z nazwiska i stopnia. Po drugie- nieodzownym elementem handlu są “czujki”- dzieciaki stojące w bramach, kręcące się po okolicy, które zwracają uwagę na policjantów i nieoznakowane radiowozy. <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:5">
      <p>I znowu, skalę takiej pracy możecie zobaczyć w The Wire, gdzie zebranie materiału na Avona Barksdale’a, nawet mimo serialowych skrótów, nie chce trwać mniej niż cały sezon. <a href="#fnref:5" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:6">
      <p>Nie zgadniecie, ale imiona i ksywki zostały zmienione. <a href="#fnref:6" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:7">
      <p>Tu polecam drugi tekst z cyklu “Policyjne mity” <a href="#fnref:7" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Niedźwiedź</name></author><category term="policja" /><category term="policja" /><category term="mity" /><category term="kryminalny" /><category term="zgwalcenie" /><category term="przepisy" /><summary type="html"><![CDATA[Jakiś czas temu, wspominając że stawianie zarzutów dilerom narkotykowym nie jest tak prostą sprawa, jak mogłoby się wydawać, obiecałem nieco bardziej przybliżyć kwestię walki z dilerami narkotyków.]]></summary></entry><entry><title type="html">O ranach bolejących i przyrządzaniu słoniny</title><link href="https://niedzwiedz.blog/nalog/2025/03/10/o-ranach-bolejacych.html" rel="alternate" type="text/html" title="O ranach bolejących i przyrządzaniu słoniny" /><published>2025-03-10T07:48:53+00:00</published><updated>2025-03-10T07:48:53+00:00</updated><id>https://niedzwiedz.blog/nalog/2025/03/10/o-ranach-bolejacych</id><content type="html" xml:base="https://niedzwiedz.blog/nalog/2025/03/10/o-ranach-bolejacych.html"><![CDATA[<p>W weekend udało mi się otworzyć sezon wspinaczkowy. Wyskoczyliśmy ze znajomymi na jeden dzień do Podlesic, bez większych planów, byle tylko dotknąć skały po zimie.</p>

<p>Wyjazd był krótki, więc nie obfitował w jakieś znaczące zdobycze wspinaczkowe, za to kilka godzin spędzonych w samochodzie sprzyjało życiowym dyskusjom. m.in. o terapiach i tym co nam dają.</p>

<p>Gadaliśmy m.in. o tym, jak udział w terapii pozwala rozwiązywać nasze problemy. I przypomniała mi się taka sytuacja, z końcówki mojej drogi na Zgierskiej.</p>

<p>Był koniec stycznia. Byłem trzeźwy od ponad roku. Parę dni wcześniej minął również rok od kiedy przekroczyłem progi Ośrodka po raz pierwszy.</p>

<p>Tego dnia skierowałem się do niewielkiej sali na pierwszym piętrze, gdzie odbywała się ostatnia z grup terapeutycznych w programie odwyku. Celem tych spotkań było ugruntowanie trzeźwych nawyków, nauczenie się koncentrowania na zdrowym przeżywaniu emocji, budowania poczucia własnej wartości i akceptacji.</p>

<p>Akurat tego dnia kilka osób kończyło grupę, a co za tym idzie- cały program terapii. Dlatego też runda wstępna przerodziła się w nieco gorzkie podsumowanie.</p>

<p>Dlaczego gorzkie? Bowiem sporo osób, nieco przygnębionych, zauważało, że kończąc terapię, mają dużo więcej problemów, niż mieli w czynnym nałogu.</p>

<p>Przyznacie, że nie brzmi to jak dobra reklama odwyku. Dlatego też rozgorzała między nami dyskusja, a do samego spostrzeżenia wracaliśmy jeszcze na spotkaniach wielokrotnie.</p>

<p>I gdzieś tam po drodze udało nam się ukuć taką metaforę, która moim zdaniem dobrze oddaje ten mechanizm.</p>

<p>Wyobraźcie sobie, że macie paskudną ranę na nodze. Próbujecie ją opatrzyć, ale niewiele to daje- rana ciągle się babrze. Jednak udaje wam się nałożyć na nią tyle opatrunków i płynu dezynfekcyjnego, że nic na zewnątrz nie wycieka i nie śmierdzi.</p>

<p>Dlatego możecie normalnie funkcjonować. Na spodniach nie widać plamy, możecie normalnie iść do pracy, albo na spotkanie ze znajomymi.</p>

<p>Co prawda trochę kulejecie, o sporcie możecie zapomnieć, podbiegnięcie do autobusu też staje się problematyczne. 
Ale w końcu da się z tym żyć- można sobie wytłumaczyć, że maratony to nie dla nas, chyba że dotyczą seriali, a gdy ktoś nam robi wymówki, że znowu spóźniliśmy się do pracy- uznajecie go za mało empatycznego, nierozumiejącego waszej sytuacji. To jego wina, nie wasza.</p>

<p>Da się, tak żyjąc, osiągnąć pozorną stabilność. Ból nogi przyjmujecie jako coś nieuchronnego, akceptujecie ograniczenia w poruszaniu się- w końcu inni mają jeszcze gorzej, więc to nie koniec świata. A tego, co dzieje się pod grubą warstwą opatrunków, nie chcecie widzieć. W końcu, póki co jest dobrze.</p>

<p>A teraz wyobraźcie sobie, że zdobywacie się wreszcie na odwagę. Idziecie do lekarza, który odwijając coraz bardziej śmierdzące bandaże, usilnie stara się nie skomentować skali waszych zaniedbań. Po prostu proponuje leczenie.</p>

<p>Tyle że to leczenie to masa problemów. Po pierwsze- lekarz musi oczyścić ranę. A to oznacza grzebanie w waszym mięsie. Bolesne jak cholera.</p>

<p>Po drugie, musicie regularnie zmieniać opatrunki- to oznacza, że łatwo tę ranę urazić, co znowu boli. Trzeba też na nią patrzeć, co najmilsze nie jest. No i te opatrunki też nie zawsze ładnie wychodzą, więc czasem coś się przesączy i spodnie do wyrzucenia.</p>

<p>Lekarz może nas skierować na fizjoterapię, co wymaga regularnego chodzenia na zajęcia. A co gorsza, fizjo może kazać nam coś robić w domu- a to oznacza, że jeśli zasiądziemy do serialu, gdzieś z tyłu głowy pojawi się poczucie winy, że powinniśmy machać nóżką, zamiast jeść chipsy.</p>

<p>Innymi słowy, jakakolwiek próba ruszenia tej sytuacji, zaowocuje masą problemów. Problemów, których byśmy nie mieli, gdybyśmy nie spróbowali tej cholernej rany odwinąć. To w końcu warto cokolwiek robić?</p>

<p>Jeśli macie w sobie choć trochę trzeźwego myślenia, zapewne już pojawia wam się dość oczywisty wniosek, płynący z tej historii.</p>

<p>Każdy z tych problemów przybliża nas do naprawy sytuacji. Każdy z nich jest oznaką tego, że zmieniamy życie na lepsze. I owszem, widzimy ich więcej, ale to nie znaczy, że wcześniej ich nie mieliśmy- po prostu miały postać jednego, dużo większego problemu.</p>

<p>Oczywiście, wiążą się one z bólem, i drobnymi upierdliwościami. Ale wiążą się też z jakąś realną zmianą. Czymś, o co w nałogu bardzo trudno.</p>

<p>Jest w programowaniu, a w zasadzie w projektowaniu oprogramowania, taka metoda, którą nazywa się carpaccio ze słonia.</p>

<p>Słoń, to problem,z którym się mierzymy. Słoń jest wielki, ciężki i ma grubą skórę. Próba zjedzenia go musi skończyć się fiaskiem. <sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup></p>

<p>Co innego, jeśli zrobimy z niego carpaccio, czyli posiekamy na cieniutkie kawałki. Każdy z nich będzie w miarę łatwy do przejedzenia. Owszem, może to zająć trochę czasu, ale poza tym wydaje się całkiem realne.</p>

<p>Tak samo w nałogu- zauważamy wielkie problemy życiowe- “nie udało mi się skończyć studiów”, “nie dam rady przebiec maratonu”, “nie jestem dość dobry, by mieć kochającą rodzinę”.</p>

<p>Takie problemy są słoniami. Przytłaczają nas, wydają się nie do ruszenia. Jedyną możliwą reakcją jest poddać się i napić- w końcu nawet jeśli zabierzemy się do pracy, to w końcu polegniemy.</p>

<p>Ale jeśli posiekamy ten problem na malutkie plasterki - “nie umiem przebiec 100m bez zadyszki”, “nie wiem jak się rozciągać”, “moja dieta nie sprzyja wysiłkowi” - każdy z nich można jakoś rozwiązać.</p>

<p>Muszę wam się przyznać, że mnie też to spotkało. Kiedy zaczynałem trzeźwieć, myślałem że wyrzucenie alkoholu z życia magicznie naprawi wszystkie moje problemy.</p>

<p>Mam parę kilo za dużo? Przecież alkohol to kalorię-od razu schudnę. Wyniki sportowe tez od razu się poprawią. Emocje? Będę je normalnie zdrowo przeżywał, więc pozbędę się zmartwień.</p>

<p>Nie będzie zmartwień o pieniądze, życie uczuciowe będzie kwitło i wyniki badań wprawią lekarzy w podziw i zdumienie.</p>

<p>Czy tak się stało? No nie. Ani nie zostałem magicznie mistrzem sportu, ani nie mam sylwetki greckiego boga, ani przeżywanie emocji nie stało się łatwiejsze.</p>

<p>Ale w każdej z tych dziedzin zrobiłem kilka małych kroczków naprzód. I cały czas robię kolejne.</p>

<p>Wreszcie widzę, że mogę cokolwiek w życiu zmieniać i jakakolwiek praca nad tą zmianą ma sens.</p>

<p>Wierzcie mi,  to już jest cholernie dużo. Wreszcie okazuje się, że można tego słonia przejeść. Nie dziś, nie jutro, ale kiedyś się uda.</p>

<p>A co dużo ważniejsze- tych plasterków nadal jest mnóstwo. Ale z każdym z nich można sobie poradzić, i zauważyć, że robi się ich trochę mniej.</p>

<p>Czego sobie i wam życzę.</p>
<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>Tak, jako wegetarianina boli mnie używanie metafory opartej o jedzenie zwierząt, dlatego chętnie przyjmę jakiś wege-analog tego obrazu. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Niedźwiedź</name></author><category term="nalog" /><category term="felieton" /><category term="ogolne" /><category term="nalog" /><summary type="html"><![CDATA[W weekend udało mi się otworzyć sezon wspinaczkowy. Wyskoczyliśmy ze znajomymi na jeden dzień do Podlesic, bez większych planów, byle tylko dotknąć skały po zimie.]]></summary></entry><entry><title type="html">Protokoły w Pythonie</title><link href="https://niedzwiedz.blog/it/2025/03/06/protokoly-w-pythonie.html" rel="alternate" type="text/html" title="Protokoły w Pythonie" /><published>2025-03-06T07:48:53+00:00</published><updated>2025-03-06T07:48:53+00:00</updated><id>https://niedzwiedz.blog/it/2025/03/06/protokoly-w-pythonie</id><content type="html" xml:base="https://niedzwiedz.blog/it/2025/03/06/protokoly-w-pythonie.html"><![CDATA[<blockquote>
  <p>“Daję słowo, zatem ja już przeszło czterdzieści lat mówię prozą, nie mając o tem żywnego  pojęcia! Jestem panu najszczerzej obowiązany, żeś mnie pouczył.”<br />
–<cite>Molier “Mieszczanin szlachcicem</cite></p>
</blockquote>

<p>Jakiś czas temu zająłem się drobnym bugiem w kodzie. Nasze modele opierają się o Pydantica, wykorzystując jako bazę, naszą wersję BaseModel, wzbogaconą o kilka metod.</p>

<p>Jedną z nich jest update modelu za pomocą słownika. To dość prosta funkcjonalność, której niestety w Pydanticu brakuje. Chodzi o to, aby podać słownik, zawierający tylko część pól, a nie cały model.</p>

<p>Działanie było bardzo proste, poza jednym aspektem- nasze modele są dość mocno zagnieżdżone, zatem jeśli pole modelu X było modelem Y, to zamiast nadpisywać wartością ze słownika, należało wywołać na instancji modelu Y metodę updatującą ze słownika.</p>

<p>Wydawało się to bardzo proste, ale Pydantic jest tak skonstruowany, że użycie metody isSubclass, zwłaszcza w przypadku gdy dane pole zawierało listę instancji naszego modelu, dawało mocno niejednoznaczne wyniki.</p>

<p>Biedziłem się nad tym cały dzień, aż w końcu skonstruowałem działające rozwiązanie, oparte na kilku różnych sprawdzeniach typów. Dumny jak paw wystawiłem pull requesta, i czekałem na pochwały.</p>

<p>Zamiast nich, dostałem krótki komentarz od jednego z dużo bardziej doświadczonych developerów - a dlaczego, zamiast sprawdzać typy, nie sprawdzisz, czy dany obiekt wystawia metodę update_from_dict.</p>

<p>Tak właśnie poznałem w działaniu praktykę zwaną “kaczkotypowaniem” (ang. duck-typing).</p>

<p>Nazwa nie wzięła się od gumowej kaczuszki, szeroko używanej w procesie tworzenia oprogramowania<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>, a od powiedzenia “jeśli to chodzi jak kaczka, ma skrzydła jak kaczka i kwacze jak kaczka, to najprawdopodobniej jest to kaczka.</p>

<p><img src="/img/posts/2025-03-06/nazi.jpg_large" class="illustration" />
<em>
    Przykładowe zastosowanie kaczkotypowania
</em></p>

<p>Jest to praktyka dość powszechna w językach dynamicznie typowanych, oznaczająca, że typ zmiennych rozpoznajemy nie poprzez przypisany im typ- w końcu ta sama zmienna może wskazywać w kilku momentach na wartości różnego typu - ale przez to jaki interfejs wystawiają.</p>

<p>Jeśli brzmi to dla was cokolwiek pokrętnie, zadajcie sobie pytanie, czy kiedykolwiek spróbowaliście stworzyć obiekt, po którym można by iterować.</p>

<p>Jak wiadomo, wymaga to dodania do klasy metod <code class="language-plaintext highlighter-rouge">__iter__()</code> oraz <code class="language-plaintext highlighter-rouge">__next__()</code>. Jeśli spróbujemy wykorzystać nasz obiekt w pętli, albo składaniu listy, Python będzie próbował wywołać te metody.</p>

<p>I zauważcie, że nie musimy w tym celu dziedziczyć po żadnej klasie, ani wskazywać interpreterowi, że oto nasza klasa umożliwia takie zachowanie. Po prostu, jeśli chodzi jak kaczka i kwacze jak kaczka, możemy traktować ją jak kaczkę.</p>

<p>Dlatego właśnie, wielu programistów, niczym pan Jourdain, nawet nie zauważa, że całe życie korzysta z kaczkotypowania.</p>

<p>I tak, jak w poprzednim wpisie wspominając o typach, pisałem raczej o tzw. Typowaniu nominalnym. Oznacza to, że obiekt <code class="language-plaintext highlighter-rouge">x</code> jest typu <code class="language-plaintext highlighter-rouge">Y</code>, jeśli jest instancją klasy <code class="language-plaintext highlighter-rouge">Y</code>, albo którejś z jej podklas<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup>.</p>

<p>Kaczkotypowanie zaś jest przykładem typowania strukturalnego. Zatem obiekt <code class="language-plaintext highlighter-rouge">x</code> jest typu <code class="language-plaintext highlighter-rouge">Y</code>, jeśli zachowuje się tak, jakbyśmy tego oczekiwali od obiektu typu <code class="language-plaintext highlighter-rouge">Y</code>. Co to dokładnie znaczy?</p>

<p>Wyobraźcie sobie, że w naszym kodzie postanawiamy zamodelować samochody. Tworzymy więc klasę bazową <code class="language-plaintext highlighter-rouge">Car</code>, która będzie zawierać wszystkie niezbędne metody i atrybuty, by nasz pojazd można było zatankować, uruchomić i ruszyć nim w drogę.</p>

<p>Część naszych użytkowników chce używać taksówek, zatem modelujemy również taki pojazd, do klasy <code class="language-plaintext highlighter-rouge">Car</code> dodając metody potrzebne, by móc naliczyć opłatę za przejazd.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Car</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">drive</span><span class="p">(</span><span class="n">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>
        <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">Wroom wroom</span><span class="sh">"</span><span class="p">)</span>
    
    <span class="k">def</span> <span class="nf">refuel</span><span class="p">(</span><span class="n">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>
        <span class="k">pass</span>

    <span class="k">def</span> <span class="nf">average_fuel_consumption</span><span class="p">(</span><span class="n">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">float</span><span class="p">:</span> 
        <span class="k">pass</span>


<span class="k">class</span> <span class="nc">Taxi</span><span class="p">(</span><span class="n">Car</span><span class="p">):</span>

    <span class="k">def</span> <span class="nf">charge_for_ride</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">destination</span><span class="p">:</span> <span class="n">Address</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>
        <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Charging fare for a ride to </span><span class="si">{</span><span class="n">destination</span><span class="si">}</span><span class="sh">"</span><span class="p">)</span>

</code></pre></div></div>

<p>Kod działa znakomicie, dzięki dziedziczeniu udało nam się ograniczyć powtarzalność kodu i w każdej klasie implementujemy tylko te metody, które świadczą o jej wyjątkowości.</p>

<p>Następnie chcemy móc skorzystać z dobrodziejstw rynku przewozów, tworzymy więc funkcję, która pozwoli użytkownikowi na przejazd taksówką</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="k">def</span> <span class="nf">take_a_taxi</span><span class="p">(</span><span class="n">taxi</span><span class="p">:</span> <span class="n">Taxi</span><span class="p">,</span> <span class="n">destination</span><span class="p">:</span> <span class="n">Address</span><span class="p">):</span>
        <span class="k">pass</span>
</code></pre></div></div>

<p>I wszystko działa wspaniale, dopóki nasi klienci nie zażyczą sobie dodania opcji przejazdu rikszą, przy użyciu już istniejących metod.</p>

<p>W końcu, argumentują, i zwykła taksówka i riksza, korzystają z podobnego algorytmu- klient wsiada, podaje adres, a kiedy tam dotrze płaci w zależności od odległości i czasu przejazdu.</p>

<p>Brzmi to prosto, ale jeśli spróbujemy dziedziczyć po klasie <code class="language-plaintext highlighter-rouge">Taxi</code>, wystawimy do użytkowników rower (rikszę), który można zatankować- wszak Taxi dziedziczy po <code class="language-plaintext highlighter-rouge">Car</code>, która to klasa wystawia metodę refuel.</p>

<p>Owszem, możemy ją nadpisać i rzucać NotImplementedError, z wiadomością, że tankowanie roweru jest cokolwiek egzotycznym pomysłem. Ale to rozwiązanie raz, że brzydkie, dwa- niezgodne z <a href="https://pl.wikipedia.org/wiki/Zasada_podstawienia_Liskov" target="_blank">zasadą podstawienia Liskov</a> , oraz <a href="https://pl.wikipedia.org/wiki/Zasada_podstawienia_Liskov" target="_blank">zasady otwarte/zamknięte</a>.</p>

<p>Możemy też napisać klasę <code class="language-plaintext highlighter-rouge">Bike</code>, dziedziczącą po niej <code class="language-plaintext highlighter-rouge">Rikshaw</code><sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup>. Wtedy jednak musimy zmienić sygnaturę funkcji <code class="language-plaintext highlighter-rouge">take_a_taxi</code>, której pierwszy argument będzie miał typ <code class="language-plaintext highlighter-rouge">Taxi | Rikshaw</code>.</p>

<p>I wydaje się to niezłym rozwiązaniem, dopóki nie zdamy sobie sprawy, że w przyszłym tygodniu nasz klient może zażyczyć sobie przejazdów motorówką, później awionetką, drezyną i kilkoma innymi pojazdami, z których każdy będzie wymagał stworzenia zupełnie innych klas bazowych.</p>

<p>A w międzyczasie nasz kod może wzbogacić się o kilka innych funkcji przyjmujących jako argumenty taksówki, riksze, lektyki, dorożki i inne pojazdy, które możemy wynająć by nas przewieziono z miejsca na miejsce.</p>

<p>Czy zatem, za każdym razem będziemy musieli dopisywać nowy pojazd do kilkunastu funkcji? Czy zachowanie bezpieczeństwa typów będzie wymagało stworzenia funkcji o takiej sygnaturze?</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Def</span> <span class="n">take_a_taxi</span><span class="p">(</span> <span class="n">taxi</span><span class="p">:</span> <span class="n">Taxi</span> <span class="o">|</span> <span class="n">Rikshaw</span> <span class="o">|</span> <span class="n">Helicopter</span> <span class="o">|</span> <span class="n">Motorboat</span> <span class="o">|</span> <span class="n">Draisine</span> <span class="o">|</span> <span class="n">Droshky</span> <span class="o">|</span> <span class="n">StageCoach</span> <span class="o">|</span><span class="p">.</span><span class="bp">...</span>
</code></pre></div></div>

<p>Sami przyznacie, że mocno zaburza to czytelność kodu.</p>

<p>Dlatego, w takiej sytuacji, na ratunek przychodzi nam opisane wyżej kaczkotypowanie. A dokładniej jego sformalizowana postać, jaką są protokoły.</p>

<p>Jeśli macie doświadczenie np. z Javą, i wykorzystywaliście w niej interfejsy, to pewnie już wiecie dokładnie o co chodzi.</p>

<p>Bowiem, o ile zwykłe klasy mają modelować (w dużym uproszczeniu) dane i zachowania z ich użyciem, to protokoły, podobnie jak interfejsy, modelują same zachowania<sup id="fnref:4"><a href="#fn:4" class="footnote" rel="footnote" role="doc-noteref">4</a></sup>.</p>

<p>Zatem, w tym przypadku, będziemy chcieli stworzyć protokół, określający te metody, które klasa musi implementować, by można było jej użyć w funkcji <code class="language-plaintext highlighter-rouge">take_a_taxi</code> - czyli na przykład <code class="language-plaintext highlighter-rouge">charge_for_ride</code>. Przykładowa implementacja będzie wyglądała tak:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">From</span> <span class="n">typing</span> <span class="kn">import</span> <span class="n">Protocol</span>

<span class="k">class</span> <span class="nc">Takeable</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">charge_for_ride</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">destination</span><span class="p">:</span> <span class="n">Address</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>
        <span class="err">…</span>
</code></pre></div></div>
<p>Jak widać, protokół, to rodzaj klasy abstrakcyjnej- zatem nie możemy utworzyć instancji tego typu. Nie mogą również dziedziczyć po jakiejkolwiek klasie konkretnej(nie-abstrakcyjnej).</p>

<p>Po protokole nie musimy dziedziczyć, wystarczy, że klasa implementuje wszystkie wskazane w nim metody. Dlatego teraz, każda klasa, niezależnie czy dziedzicząca po <code class="language-plaintext highlighter-rouge">Bike</code>, <code class="language-plaintext highlighter-rouge">Car</code>, czy <code class="language-plaintext highlighter-rouge">Train</code>, wystawiająca metodę <code class="language-plaintext highlighter-rouge">charge_for_ride</code>, o tej samej sygnaturze, będzie uznana za przedstawiciela typu Takeable.</p>

<p>Zatem nasza funkcja ma <code class="language-plaintext highlighter-rouge">take_a_taxi</code> ma znacznie prostszą sygnaturę. Jej pierwszy argument to <code class="language-plaintext highlighter-rouge">taxi: Takeable</code>. Jeśli będziemy implementować kolejne typy pojazdów, nie musimy niczego więcej zmieniać, wystarczy, że zaimplementujemy w nich metodę <code class="language-plaintext highlighter-rouge">charge_for_ride</code>.</p>

<p>Jeśli nadal nie jesteście przekonani do tego rozwiązania, wyobraźcie sobie, że nasza funkcja do przejazdów stanowi część biblioteki. Nasi użytkownicy to programiści, którzy będą chcieli zastosować ją w swoich projektach, używając swoich typów danych.</p>

<p>Przy podejściu nominalnym, musieli by dziedziczyć po którejś z przygotowanych przez nas klas- przez co musieli by się zastanawiać, co ma zwracać odziedziczona z klasy <code class="language-plaintext highlighter-rouge">Car</code> metoda <code class="language-plaintext highlighter-rouge">average_fuel_consumption</code> w odniesieniu do używanych przez nich sanek, albo teleportu międzygalaktycznego, albo czy któraś z metod nie przysłoni czegoś co napisali wcześniej.</p>

<p>Dzięki protokołom zaś, taka integracja jest niemal bezbolesna. Nie musimy nawet w żaden sposób oznaczać, że nasza klasa implementuje dany protokół. Nie musimy dziedziczyć po protokole, ani nawet go importować.</p>

<p>Jeśli nasz protokół jest w pliku <code class="language-plaintext highlighter-rouge">takeable.py</code> to implementując ani w pliku <code class="language-plaintext highlighter-rouge">stagecoach.py</code>, zawierającym klasę implementującą protokół, ani <code class="language-plaintext highlighter-rouge">taxi_rides.py</code> zawierającym funkcje przyjmujące argumenty typu <code class="language-plaintext highlighter-rouge">Takeable</code> nie musimy go importować. Interpreter ogarnie to za nas</p>

<p>No dobrze. Ale co, jeśli dojdzie do sytuacji, w której jednak potrzebujemy typowania nominalnego? W jakimś miejscu kodu, chcielibyśmy sprawdzić, czy wartość danej zmiennej ma typ str, int albo Takeable. Jak to zrobić?</p>

<p>Biblioteka typing ma na tę okazję dekorator <code class="language-plaintext highlighter-rouge">@runtime_checkable</code>. Jeśli dodamy go do definicji protokołu, to wszystkie obiekty wystawiające metody protokołu, zostaną uznane za jego instancje.
W praktyce wygląda to tak:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">typing</span> <span class="kn">import</span> <span class="n">Protocol</span><span class="p">,</span> <span class="n">runtime_checkable</span>

<span class="nd">@runtime_checkable</span>
<span class="k">class</span> <span class="nc">Takeable</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">charge_for_ride</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">destination</span><span class="p">:</span> <span class="n">Address</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>
        <span class="err">…</span>

<span class="k">class</span> <span class="nc">Carriage</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">charge_for_ride</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">destination</span><span class="p">:</span> <span class="n">Address</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>
        <span class="k">pass</span>

<span class="n">carriage</span> <span class="o">=</span> <span class="nc">Carriage</span><span class="p">()</span>
<span class="nf">is_instance</span><span class="p">(</span><span class="n">carriage</span><span class="p">,</span><span class="n">Takeable</span><span class="p">)</span> <span class="c1"># To zwraca True
</span></code></pre></div></div>

<p>Na koniec warto jeszcze wspomnieć o przyjętym przeze mnie nazewnictwie. Większość materiałów
dotyczących protokołów nie zwraca uwagi na ich nazwy- są one podobne jak te, które nadajemy
zwykłym klasom.</p>

<p>Jednak pracując w Scali, przyzwyczaiłem się, że traity (czyli odpowiednik m.in. interfejsów), 
często nazywa się przymiotnikami odczasownikowymi. Mamy zatem <code class="language-plaintext highlighter-rouge">Startable</code>, <code class="language-plaintext highlighter-rouge">Stopable</code>, <code class="language-plaintext highlighter-rouge">Configurable</code>.</p>

<p>Jak wspomniałem wcześniej, interfejsy okreslają zachowania- zatem taka właśnie konwencja ich
nazewnictwa wydaje mi się najlepsza. Po pierwsze- odróżnia je od klas. Po drugie- jasno wskazuje
na to, jakie zachowanie opisują.</p>

<p>Co więcej, konsekwentne trzymanie się takiego nazewnictwa, może pomóc nam w utrzymaniu <a href="https://pl.wikipedia.org/wiki/Zasada_jednej_odpowiedzialności" target="_blank">zasady jednej odpowiedzialności</a>.</p>

<p>W końcu, jeśli protokół nazywa się <code class="language-plaintext highlighter-rouge">Startable</code> a nas korci, by dodać do niego metodę <code class="language-plaintext highlighter-rouge">stop</code>, może łatwiej będzie nam zastanowić się, czy stanowi ona warunek konieczny, by uznać coś za “startowalne”? A może to czas na wydzielenie jej do kolejnego protokołu?</p>

<p>Oczywiście, nie jest to w żaden sposób wymagane, ani przez konwencję, ani tym bardziej interpreter.</p>

<p>Wierzę jednak, że dobry kod to również dobre nazewnictwo, które wspiera nas w pracy. Ale o tym napiszę innym razem.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>O tym jak i dlaczego napiszę w niedługiej przyszłości <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2">
      <p>Uważny czytelnik może się przyczepić, że nie dokońca- i słusznie, ale o pojęciach ko- i kontra-wariancji napiszę w bliżej nieokreślonej (acz raczej niedalekiej) przyszłości. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3">
      <p>Dopiero po napisaniu tego zdania, sprawdziłem że w wielu krajach rikszami określa się również wózki ciągnięte przez idącego pieszo “kierowcę”. Co oczywiście pokazuje dalsze komplikacje w budowaniu naszego modelu rzeczywistości, ale dla klarowności wywodu pozostańmy przy rikszach opartych na budowie roweru. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4">
      <p>Uważny czytelnik zada zapewne pytanie- czego użyć, jeśli chcę modelować same dane. I bardzo słusznie- służą do tego dataclassy, którym poświęcony będzie kolejny wpis. <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Niedźwiedź</name></author><category term="it" /><category term="python" /><category term="typowanie" /><category term="protokoły" /><category term="protocol" /><category term="typing" /><summary type="html"><![CDATA[“Daję słowo, zatem ja już przeszło czterdzieści lat mówię prozą, nie mając o tem żywnego pojęcia! Jestem panu najszczerzej obowiązany, żeś mnie pouczył.” –Molier “Mieszczanin szlachcicem]]></summary></entry><entry><title type="html">Policyjne mity cz.4 - Zgwałcenie i domniemanie niewinności</title><link href="https://niedzwiedz.blog/policja/2025/02/22/zgwalcenie-domniemanie-niewinnosci.html" rel="alternate" type="text/html" title="Policyjne mity cz.4 - Zgwałcenie i domniemanie niewinności" /><published>2025-02-22T07:48:53+00:00</published><updated>2025-02-22T07:48:53+00:00</updated><id>https://niedzwiedz.blog/policja/2025/02/22/zgwalcenie-domniemanie-niewinnosci</id><content type="html" xml:base="https://niedzwiedz.blog/policja/2025/02/22/zgwalcenie-domniemanie-niewinnosci.html"><![CDATA[<p>Od paru dni, a konkretnie od 13 lutego, żyjemy w nowej rzeczywistości. Oczywiście, rozgaszczanie się nowej władzy w USA sprawia, że dziennikarze obwieszczają takie zmiany niemal codziennie.</p>

<p>Ale nowość, o której dziś piszę, ani nie jest zaskoczeniem, ani nie ma takiego potencjału memicznego, więc weszła w życie, zasługując jedynie na kilka niewielkich wzmianek.</p>

<p>Chodzi mianowicie o nową definicję zgwałcenia, która co prawda uchwalona została w lipcu 2024, ale dłuższe <em>vacatio legis</em> sprawiło, że w życie weszła dopiero 13 lutego.</p>

<p>Od momentu rozpoczęcia prac legislacyjnych, zmiana ta budziła dużo kontrowersji. Przez jednych była przedstawiana jako cudowna recepta, która rozwiąże wszystkie problemy, na jakie Policja i Prokuratura natrafiają, ścigając gwałcicieli.</p>

<p>Z drugiej strony, padały oskarżenia o podważanie konstytucyjnej zasady domniemania niewinności.</p>

<p>Jedno i drugie można śmiało uznać za mit, a jako że pracowałem w komórce, która m.in. zajmowała się zgwałceniami, śpieszę wyjaśnić dlaczego</p>

<h2 id="nowa-definicja-a-domniemanie-niewinności">Nowa definicja a domniemanie niewinności</h2>

<p>Zacznijmy od, najczęściej podnoszonego przez przeciwników nowych przepisów, zarzutu. Wchodząca w życie definicja, ma według niektórych komentujących, przeczyć zasadzie domniemania niewinności.</p>

<p>To dość kuriozalny zarzut, ale, co ciekawe, pada nie tylko ze strony internetowych pieniaczy, ale i ludzi mieniących się ekspertami od prawa, jak na przykład <a href="https://ordoiuris.pl/wolnosci-obywatelskie/koniecznosc-udowadniania-wlasnej-niewinnosci-nowa-definicja-zgwalcenia-w" target="_blank">Instytutu Na Rzecz Kultury Prawnej Ordo Iuris</a>.</p>

<p>O co chodzi? Zobaczmy na czym polega zmiana, która wzbudziła te kontrowersje:</p>

<table>
  <thead>
    <tr>
      <th>Stara wersja</th>
      <th>Nowa wersja</th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Art. 197. § 1. Kto przemocą, groźbą bezprawną lub podstępem doprowadza inną osobę do obcowania płciowego, podlega karze pozbawienia wolności od lat 2 do 15.</td>
      <td>Art. 197. § 1. Kto doprowadza inną osobę do obcowania płciowego przemocą, groźbą bezprawną, podstępem <strong>lub w inny sposób mimo braku jej zgody</strong>, podlega karze pozbawienia wolności od lat 2 do 15.</td>
      <td> </td>
    </tr>
  </tbody>
</table>

<p>Ten niewielki dopisek na temat braku zgody spowodował lawinę komentarzy, dopisujących do niego daleko idące zmiany w procedurze karnej.</p>

<p>Wedle ich autorów, skoro brak zgody ma być przesłanką do stwierdzenia zaistnienia przestępstwa zgwałcenia, to automatycznie oznacza, że na podejrzanego przerzucona zostanie odpowiedzialność za udowodnienie, że do stosunku doszło za zgodą wszystkich zainteresowanych stron.</p>

<p>To wniosek tyleż ciekawy, co bezsensowny. Domniemanie niewinności jest zapisane zarówno w kodeksie karnym (<a href="https://lexlege.pl/kpk/art-5/" target="_blank">art. 5</a> ), jak i konstytucji (<a href="https://lexlege.pl/kpk/art-5/" target="_blank">art. 42 par. 3</a> ).</p>

<p>I o ile przepis ustawowy, można by pewnie jakoś wyłączyć innym, bardziej szczegółowym przepisem ustawowym, to z zapisami konstytucji mogłoby być nieco ciężej.</p>

<p>Zresztą, warto zwrócić uwagę, że nigdzie nie znajdziemy analiz, w jaki sposób to wyłączenie domniemania niewinności miałoby działać, i z którego fragmentu nowelizacji wynikać.</p>

<p>Autorzy analizy Ordo Iuris poprzestają na kilku mglistych tezach, że będzie to zależało od interpretacji. No nie będzie, zresztą- nie jest to zdanie moje, czyli mądrali z internetu, który prawa nie studiował.</p>

<p>Dość jasno mówi o tym też <a href="https://legalis.pl/seks-bez-zgody-zostanie-uznany-za-gwalt/#:~:text=Domniemanie%20niewinno%C5%9Bci%20pozostanie&amp;text=Wszelkie%20w%C4%85tpliwo%C5%9Bci%20co%20do%20wype%C5%82nienia,Ma%C5%82ecki" target="_blank">dr hab. Mikołaj Małecki</a> z Uniwersytetu Jagiellońskiego, autor bloga Dogmaty Karnisty.</p>

<p>Nadal, ciężar dowodowy spoczywać będzie na oskarżycielu- Prokuratorze i policjantach prowadzących postępowanie. To na nich spoczywać będzie odpowiedzialność za udowodnienie, że do stosunku doszło bez zgody jednej ze stron.</p>

<p>A to prowadzi nas do drugiego, nieco bardziej przykrego z punktu widzenia policjanta, mitu.</p>

<h2 id="nowa-definicja-a-wykrywalność">Nowa definicja a wykrywalność</h2>

<p>Jeśli ktoś miał nadzieję, że zmiany w przepisach przyniosą sprawiedliwość i wyrównanie krzywd, a przede wszystkim sprawią, że większość spraw o zgwałcenie nie będzie kończyć się umorzeniem, to niestety mam złą wiadomość.</p>

<p>Owszem, nowa definicja pomoże uniknąć żenujących wyroków, w rodzaju <a href="https://legalis.pl/seks-bez-zgody-zostanie-uznany-za-gwalt/#:~:text=Domniemanie%20niewinno%C5%9Bci%20pozostanie&amp;text=Wszelkie%20w%C4%85tpliwo%C5%9Bci%20co%20do%20wype%C5%82nienia,Ma%C5%82ecki" target="_blank">tego z Wrocławia</a> , gdzie sąd uznał, że nie doszło do zgwałcenia, bo 14-letnia ofiara nie krzyczała ani nie broniła się.</p>

<p>Owszem, może być pomocna w takich sytuacjach, jak ta do której doszło w <a href="https://niedzwiedz.blog/policja/felieton/2024/03/02/Zbrodnia-na-Zurawiej.html" target="_blank">marcu ub. roku w Warszawie</a>- tam też ofiara nie krzyczała i się nie broniła.</p>

<p>Ale to jest margines (niezwykle istotny, i nie chciałbym tu umniejszać wagi tych spraw) zgwałceń. W powszechnej świadomości, zgwałcenie kojarzy się z przestępstwem, do którego dochodzi w ciemnej uliczce, gdy lekko pijana, i wyzywająco ubrana kobieta, beztrosko wraca nocą do domu.</p>

<p>Ale tego typu zgwałcenia są rzadkością. Dane pokazują, że znaczna część zgwałceń popełniana jest przez osoby znane, albo przynajmniej pozostające w stosunku towarzyskim z ofiarą<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>. O tym, że strój ofiary nie ma najmniejszego znaczenia, nie wspominając<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup>.</p>

<p>I niestety, są to w większości przestępstwa, w których brak jakichkolwiek dowodów, poza zeznaniami osoby pokrzywdzonej i sprawcy. A zatem, niezależnie czy oskarżenie ma udowodnić wystąpienie gróźb karalnych czy brak zgody- nie ma na czym się oprzeć.</p>

<p>Tutaj pewnie miłośnicy literatury kryminalnej zakrzykną “Hola, hola! Przecież są badania DNA, przecież sprawca może zostawić masę śladów- włosy, nasienie, naskórek pod paznokciami ofiary. Z takim materiałem skazanie to pestka!”.</p>

<p>Pozostaje odpowiedzieć, owszem- nietrudno po zgwałceniu zabezpieczyć liczne dowody, jednoznacznie wskazujące na to kto z kim odbył stosunek seksualny. Sęk w tym, że to niczego nie dowodzi w kontekście zgwałcenia.</p>

<p>Wyobraźcie sobie taką sytuację- pracownicy firmy wyjeżdżają na imprezę integracyjną do hotelu pod Warszawą. Biorą udział w różnego rodzaju atrakcjach, uroczystej kolacji. A potem wyciągają flaszki i w podgrupach integrują się, spożywając alkohol.</p>

<p>W pewnym momencie dwie osoby oddalają się od grupy i znikają w jednym z pokoi. Następnego dnia rano, jedna z nich składa zawiadomienie o zgwałceniu.</p>

<p>W toku przesłuchania, osoba pokrzywdzona zeznaje, że w trakcie imprezy poczuła się zmęczona i chciała iść do swojego pokoju. Sprawca, pod pozorem odprowadzenia jej, poszedł wraz z nią a następnie zmusił do odbycia stosunku.</p>

<p>Natychmiast przesłuchany sprawca twierdzi natomiast, że ofiara była całkiem przytomna, i kiedy znaleźli się sam na sam,  entuzjastycznie zachęcała do stosunku- zarówno słowem jak i czynem.</p>

<p>W takim przypadku ślady udowadniające, że doszło do stosunku, są nam po nic. W końcu obie strony są zgodne co do tego, że uprawiały seks. Przedmiotem sporu jest to, czy działo się to za obopólną zgodą.</p>

<p>A tu brak jakichkolwiek źródeł dowodowych- owszem, należy przesłuchać innych uczestników imprezy, ale najczęściej odpowiedzą, że nie widzieli nawet dokładnie momentu, w którym ta dwójka się oddaliła. W końcu wszyscy mieli w czubie.</p>

<p>Owszem, należy zabezpieczyć monitoring z korytarzy hotelowych. Ale najczęściej pokaże on po prostu dwie osoby, zmierzające chwiejnym krokiem w jednym kierunku.</p>

<p>I skoro, jak już ustaliliśmy w pierwszej części- nowe przepisy nie znoszą zasady domniemania niewinności, ciężko jest udowodnić, że do stosunku doszło bez zgody.</p>

<p>A skoro wszystkie wątpliwości należy rozwiązywać na korzyść oskarżonego, to najczęściej taka sprawa zostaje umorzona, właśnie przez niemożność udowodnienia ponad wszelką wątpliwość tego braku zgody.
I owszem, w pełni rozumiem tragizm tej sytuacji. Zasada, na której opieramy swoje poczucie tego, czym jest sprawiedliwy proces, stanowi naczelną przeszkodę w skazaniu sprawców jednego z najcięższych przestępstw.</p>

<p>Rozumiem nawet, skąd biorą się głosy, by <a href="https://niedzwiedz.blog/policja/felieton/2024/03/02/Zbrodnia-na-Zurawiej.html" target="_blank">w przypadku zgwałcenia to domniemanie winy wyłączyć</a>. Choć nie umiem się z taką propozycją zgodzić, to wierzę że poczucie niesprawiedliwości i nieprzystawania rozwiązań prawnych do jakiejkolwiek rzeczywistości może budzić nader uzasadnioną frustrację.</p>

<p>Dlatego też nie uważam, że nowe przepisy wprowadzą jakieś znaczące zmiany, zarówno jeśli chodzi o statystyki, jak i poczucie sprawiedliwości i bezpieczeństwa u ofiar zgwałceń.</p>

<p>Ale na pewno jest to krok w dobrą stronę. Tyle, że należy go traktować jako bardzo drobny, pierwszy krok na długiej i wyboistej drodze, a nie przełomowe rozwiązanie.</p>

<p>Bo od takiego rozwiązania dzieli nas jeszcze bardzo wiele, choć mam nadzieję, że debata na temat możliwych dalszych działań będzie trwać, czego i czytelnikom i sobie bardzo życzę.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>Przykładowo: <a href="https://cpk.org.pl/wp-content/uploads/2017/09/gwalt_2014_druk_20.02.15.pdf" target="_blank">“Jeśli jesteś ofiarą gwałtu- poradnik prawny dla kobiet”, Centrum Praw Kobiet 2014</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2">
      <p>Z moich własnych doświadczeń mogę wspomnieć sprawę, w której ofiarą padła 60-letnia sprzątaczka z dużego zakładu przemysłowego. Szła na przystanek autobusowy w służbowym fartuchu, na który nałożyła połatany płaszcz na wacie, sięgający do kostek. Ale jeśli potrzebujecie zobaczyć to na własne oczy- <a href="https://www.spotlightinitiative.org/news/what-were-you-wearing-un-exhibit-demands-justice-survivors-sexual-violence" target="_blank">powstało kilka wystaw</a> <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Niedźwiedź</name></author><category term="policja" /><category term="policja" /><category term="mity" /><category term="kryminalny" /><category term="zgwalcenie" /><category term="przepisy" /><summary type="html"><![CDATA[Od paru dni, a konkretnie od 13 lutego, żyjemy w nowej rzeczywistości. Oczywiście, rozgaszczanie się nowej władzy w USA sprawia, że dziennikarze obwieszczają takie zmiany niemal codziennie.]]></summary></entry><entry><title type="html">Typowanie w Pythonie</title><link href="https://niedzwiedz.blog/it/2025/02/01/typowanie-w-pythonie.html" rel="alternate" type="text/html" title="Typowanie w Pythonie" /><published>2025-02-01T07:48:53+00:00</published><updated>2025-02-01T07:48:53+00:00</updated><id>https://niedzwiedz.blog/it/2025/02/01/typowanie-w-pythonie</id><content type="html" xml:base="https://niedzwiedz.blog/it/2025/02/01/typowanie-w-pythonie.html"><![CDATA[<p>Jak powszechnie wiadomo, Python należy do języków dynamicznie typowanych. W odróżnieniu od np. C, czy Javy, w momencie tworzenia zmiennej nie musimy deklarować jej typu. Ba, nie musimy go nawet znać.
Dlatego, poniższy kod zadziała dla dowolnych typów, dla których zdefiniowano operator +:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">print_sum</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
    <span class="nf">print</span><span class="p">(</span><span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">)</span>

<span class="n">a</span> <span class="o">=</span> <span class="mi">15</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">25</span>
<span class="nf">print_sum</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span> <span class="c1"># 40
</span>
<span class="n">c</span> <span class="o">=</span> <span class="sh">"</span><span class="s">fifteen</span><span class="sh">"</span>
<span class="n">d</span> <span class="o">=</span> <span class="sh">"</span><span class="s">twenty-five</span><span class="sh">"</span>
<span class="nf">print_sum</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span> <span class="c1"># "fifteentwenty-five"
</span>
<span class="n">e</span> <span class="o">=</span> <span class="sh">"</span><span class="s">ten</span><span class="sh">"</span>
<span class="n">f</span> <span class="o">=</span> <span class="mf">2.45</span>
<span class="nf">print_sum</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span> <span class="c1"># TypeError: can only concatenate str (not "float") to str
</span></code></pre></div></div>

<p>Bywa to zbawieniem, zwłaszcza dla początkujących programistów, którym odpada przynajmniej jedno zmartwienie przy oblekaniu algorytmu w ciało funkcji.</p>

<p>Bywa to również powodem do dumy- w końcu zen Pythona zakłada prostotę i elastyczność. Tak samo jak nie ma w języku średników na końcu instrukcji, ani nawiasów klamrowych<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup></p>

<p>Ale ma też poważniejsze zalety. Choćby taką, że znacznie upraszcza stosowanie polimorfizmu-  w języku statycznie typowanym musielibyśmy z góry zdefiniować jaki typ danych przyjmie nasza funkcja, i najpewniej napisać kilka jej wariantów dla różnych typów.</p>

<p>Jedną z naczelnych zasad Pythona jest również estetyka i czytelność kodu. A pozbycie się zarówno typów zmiennych, jak i słów kluczowych przy ich definicji niewątpliwie pozwala się pozbyć nadmiarowych znaków, przez co łatwiej wychwycić esencję myśli programisty.</p>

<p><img src="/img/posts/2025-02-01/types.webp" class="illustration" /></p>

<p>Jednak, jeśli zaczniecie pracować nad bardziej złożonymi projektami, zwłaszcza w zespole, w którym będzie ktoś więcej poza wami, szybko okaże się, że te zalety mogły przesłonić kilka podstawowych wad.</p>

<p>Jedną z nich jest, o ironio, czytelność kodu. Jak wiemy, powinniśmy programować tak, jakby nasz kod miał być czytany przez psychopatyczne klauna ze strzelbą i notatnikiem pełnym adresów naszych bliskich. Chcemy, żeby ten klaun był spokojny i zadowolony. Dlatego zastanówmy się, która z poniższych funkcji jest czytelniejsza:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">do_something_weird</span><span class="p">(</span>
        <span class="n">person_age</span><span class="p">,</span> 
        <span class="n">book_release_year</span><span class="p">,</span> 
        <span class="n">lunar_phase</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">[</span><span class="nf">do_some_magic</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">book_release_year</span><span class="p">)</span> 
        <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">person_age</span> 
        <span class="k">if</span> <span class="nf">some_boring_function</span><span class="p">(</span><span class="n">lunar_phase</span><span class="p">)]</span>
</code></pre></div></div>

<p>Czy może:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">do_something_weird</span><span class="p">(</span>
        <span class="n">person_age</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
        <span class="n">book_release_year</span><span class="p">:</span> <span class="n">Datetime</span><span class="p">,</span>
        <span class="n">lunar_phase</span><span class="p">:</span> <span class="n">LUNAR_PHASE</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
    <span class="k">return</span> <span class="p">[</span><span class="nf">do_some_magic</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">book_release_year</span><span class="p">)</span> 
        <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">person_age</span> 
        <span class="k">if</span> <span class="nf">some_boring_function</span><span class="p">(</span><span class="n">lunar_phase</span><span class="p">)]</span>
</code></pre></div></div>

<p>Jeśli nie możecie się zdecydować, zadajcie sobie proste pytanie: ile czasu zajęło by wam zgadnięcie, że wiek osoby należy przekazać słownie (no dobra- int raczej nie jest iterable, więc wiadomo, że liczba tu nie zadziała, ale to nie do końca odpowiada na pytanie).</p>

<p>Stąd właśnie, wraz z wydaniem wersji 3.5, Python wzbogacił się o adnotacje i bibliotekę Typing. Nie są one w żaden sposób obowiązkowe, ani nie wpływają na wykonanie kodu, a jednak mają kolosalne znaczenie.</p>

<p>Po pierwsze- co już wskazaliśmy, znacznie ułatwiają czytanie kodu. Dla początkującego programisty, tworzącego swój pierwszy projekt, może się to czasem wydać nadmiarowe.</p>

<p>W końcu stara się nazywać zmienne i funkcje w sposób jasny i czytelny (choć i tak połowa kończy nazwana <code class="language-plaintext highlighter-rouge">wyn_wysz_ksz</code>, albo <code class="language-plaintext highlighter-rouge">roztenteguj(b)</code>).</p>

<p>Jako że żyje swoim projektem i napisał każdy znak w jego codebase, to nie ma problemu ze zrozumieniem, co która funkcja robi, i w jaki sposób działa przepływ danych.</p>

<p>Ba, typowanie jest czasem nawet kłopotliwe- skąd mam wiedzieć, co zwróci moja funkcja, zanim ją napiszę. Albo- skoro język jest dynamicznie typowany, to dlaczego funkcja nie może w jednym przypadku zwracać liczby, a w innym- listy liczb?</p>

<p>Jednak wierzcie mi, kiedy wpada się w cudzy legacy code, w dodatku od dawna nieruszany, jasne i przejrzyste typy są wybawieniem.</p>

<p>I nie musi to być nawet wynikiem tego, że poprzedni zespół składał się z pawianów szprycowanych kofeiną, których lead zapijał kolejny rozwód. Nawet świetnie wymyślony, dobrze napisany kod, pozbawiony typów, może sprawić na wejściu sporo kłopotów.</p>

<p>Ot po prostu, dzięki adnotacjom, ja wiem co zwraca dana funkcja i jakiego typu argumenty przyjmuje- to znacznie upraszcza korzystanie z nich i debugowanie. Wiemy co do funkcji podać, wiemy co powinna zwrócić, łatwiej więc wgryźć się w to, co się w niej dzieje.</p>

<p>Co więcej, wie to też edytor. Jeśli użyjemy prostej klasy:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Duck</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">quack</span><span class="p">():</span>
	<span class="nf">print</span><span class="p">(</span><span class="err">“</span><span class="n">Quack</span><span class="err">!”</span><span class="p">)</span>
</code></pre></div></div>

<p>I przekażemy jej instancję do funkcji, to “quack” będziemy musieli napisać z palca. Bo w końcu skąd ten biedny edytor ma wiedzieć, że pływający ptak to właśnie kaczka?</p>

<p><img src="/img/posts/2025-02-01/1.png" class="illustration" /></p>

<p>W przypadku naszej kaczki, tracimy tylko kilka chwil, potrzebnych na napisanie prostej nazwy. Ale co jeśli operujemy na klasach, które mają 40 różnych metod?</p>

<p><img src="/img/posts/2025-02-01/2.png" class="illustration" /></p>

<p>Jak widać, proste dodanie typu może znacząco wpłynąć na wygodę pisania kodu, ale również i na bezpieczeństwo. I nie chodzi tylko i wyłącznie o możliwość walnięcia, trudnej do znalezienia, literówki.</p>

<p>Jeśli edytor wie, jaki jest zwracany typ funkcji, może wyłapać momenty, w których na przykład podajemy do funkcji string zamiast inta.</p>

<p>I wreszcie jeden z moich ulubionych argumentów. John DeGoes, w pierwszej wersji podręcznika “Zionomicon”<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup>. Otóż deklaracja funkcji jest pewnego rodzaju obietnicą. Kontraktem zawieranym pomiędzy programistą a użytkownikiem kodu- czy będzie to jego kolega z zespołu, czy użytkownik biblioteki.</p>

<p>Brzmi to oczywiście górnolotnie, ale jak działa w praktyce? W tym samy “Zionomiconie”, deGoes nie tłumaczy implementacji kolejnych funkcji czy metod. Po prostu podaje definicje- typów, funkcji, traitów<sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup>. To wystarczy by zrozumieć, jak działają. To doskonała ilustracja znanej prawdy, że poprawnie napisany kod jest samodokumentujący.</p>

<p>Oczywiście, ktoś może powiedzieć- to po co pisać w Pythonie, skoro można zająć się językami, które typowania wymagają? Cytując klasyka - niech te plusy nie przesłonią nam minusów.</p>

<p>Python jest nadal językiem prostym, czytelnym i pięknym. Z reguły wystarczy mi około 5 minut obcowania z kodem w Javie, żeby czuć ulgę, że nie muszę niczego w niej pisać- ilość boilerplate`u jest tam zatrważająca a kod rzadko kiedy da się określić inaczej niż “potwornie brzydki”.</p>

<p>Nawet jeśli bardzo cenicie sobie dynamiczne typowanie, nadal nic nie stoi na przeszkodzie,
abyście zmiennej najpierw nadawali wartość string, potem int, a potem worek_kartofli.</p>

<p>Natomiast w bardziej rozbudowanych projektach, lepiej takie rzeczy robić wewnątrz funkcji,
natomiast typy wejścia i wyjścia niech będą stałe i jasno określone. I wasz zespół, i wy z przyszłości sobie za to podziękujecie.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>Swoją drogą, to jeden z bardziej uroczych easter eggów Pythona. Jeśli chcielibyście używać nawiasów klamrowych, niczym w C czy Javie, wykonajcie instrukcję:</p>

      <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">__future__</span> <span class="kn">import</span> <span class="n">braces</span>
</code></pre></div>      </div>
      <p><a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2">
      <p>Nie wiem, czy w kolejnych to zdanie również jest zawarte. Nawet jeśli nie piszecie w Scali, to zachęcam do zapoznania się. Książkę można otrzymać za darmo na stronie: https://www.zionomicon.com/ <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3">
      <p>Wiem, po polsku powinno się mówić cech. Ale “trait” to słowo kluczowe Scali, i jakbym nie kochał spolszczania terminologii, uważam że lepiej używać tego pojęcia w takim brzmieniu, w jakim przyjmuje je kompilator. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Niedźwiedź</name></author><category term="it" /><category term="python" /><category term="typowanie" /><summary type="html"><![CDATA[Jak powszechnie wiadomo, Python należy do języków dynamicznie typowanych. W odróżnieniu od np. C, czy Javy, w momencie tworzenia zmiennej nie musimy deklarować jej typu. Ba, nie musimy go nawet znać. Dlatego, poniższy kod zadziała dla dowolnych typów, dla których zdefiniowano operator +:]]></summary></entry></feed>