Implementowanie mechanizmów rurociągów od podstaw w Pythonie

Zawsze istnieje chęć odtworzenia fascynującej składni w Pythonie. Ciekawym przykładem jest orurowanie.

Zdjęcie autorstwa Towfiqu barbhuiya na Unsplash

W poprzednich samouczkach widzieliśmy, jak zaimplementować zachowanie wysokiego poziomu za pomocą metod Dunder i jak metoda częściowa oferowana przez moduł functools może wykorzystać wielokrotność argumentów.

Interesuje mnie wykorzystanie obu filarów Pythona do zaimplementowania pozoru zachowania PIPEY , czyli zbudowania mechanizmu pipingu, który osiągnąłby serię następujących po sobie operacji na danych, takich jak:

pipe | operation1 >> operation2 >> operation3 >> ..  >> operationN

W tym celu:

  • Najpierw skonstruuj podstawową, Partialkonfigurowalną klasę, która będzie działać jako functools.partialmoduł.
  • Wprowadź więcej możliwości do Partialklasy.
  • Połącz to wszystko w Pipeklasie.

Jak już wiesz, partialmetoda dostarczona w functoolssłuży do zamrożenia części argumentów funkcji i daje z kolei nową funkcję.

Obraz autora

Moduł partialma mniej więcej następującą implementację:

Przetestujmy to na tym samym przykładzie, o którym mowa w oficjalnej dokumentacji:

>>> basetwo = Partial(int, base=2)
>>> basetwo('1001')
... 9

Aby emulować zachowanie arytmetyczne, móc używać odbitego przesunięcia w prawo, ( >> )a także używać potoku jako wywoływanego, musimy zaimplementować dwie specjalne metody: __rshift__i __call__. Pozwól, że najpierw pokażę, jak to się robi, a potem wyjaśnię:

Różnica w stosunku do pierwszej podstawowej Partialimplementacji pod względem inicjalizacji instancji polega na naturze atrybutów. Musielibyśmy skonstruować rodzaj akumulatora, z którego skorzystalibyśmy podczas prawego przełożenia z inną Partialinstancją.

Proszę zauważyć, jak __rshift__metoda została napisana, wszystko sprowadza się do dołączenia otherinformacji częściowych (argumenty funkcji, argumentów i słów kluczowych) do pierwszej, dzięki czemu śledzimy kolejność, w jakiej potok jest zorientowany i powinien być wykonywany. Po ustanowieniu potoku łańcuch funkcji Callables uruchamia obliczenia od lewej do prawej. Pierwsza wywoływalna oblicza wynik, który z kolei staje się danymi wejściowymi do następnego.

Podajmy przykład:

>>> first_pipeline = Partial(pow,2) >> Partial(pow,3) >> Partial(pow, 5) 
>>>
>>> first_pipeline(4)
... 1152921504606846976
>>> ((4 ** 2) ** 3 ) ** 5 
... 1152921504606846976

Jednak z pewnością nie chcemy w widoczny sposób wywoływać częściowego za każdym razem, gdy chcemy dodać coś do naszego potoku.

Zapiszmy dostosowane wersje funkcji unitarnych, których potrzebowalibyśmy do naszych celów. Zdefiniujmy powerfunkcję i addfunkcję:

power = lambda x: Partial(lambda x_, n: pow(x_, n), x)
add = lambda x: Partial(lambda x_, n: x_ + n, x)

Partial(lambda x_, n: pow(x_, n), x)zamraża pierwszy argument x_funkcji lambda.
Ponieważ xjest to zmienna, która przedstawiałaby dane wejściowe lub wynik poprzedniego wywołania, sensowne jest zawinięcie tego Partialw inną lambdafunkcję.

>>> power = lambda x: Partial(lambda x_, n: pow(x_, n), x)
>>> add = lambda x: Partial(lambda x_, n: x_ + n, x)
>>> element = power(2) >> add(4) >> power(2) >> add(2)
>>> element(16)
>>> 67602

>>> ((((16 ** 2) + 4 ) ** 2 ) + 2)
>>> 67602

A może zainwestujesz w więcej elegancji? Zbierzmy to wszystko w Pipeklasę:

Z naszymi Piperzeczami nabierają znaczenia:

>>> element = Pipe() | power(2) >> add(4) >> power(2) >> add(2)
>>> element 
... <__main__.Pipe at 0x7f869c3606a0>
>>> element(16)
... 67602

Co powiesz na przetestowanie naszego mechanizmu z innym rodzajem danych, powiedzmy np. listami!
Najwyraźniej deklarujemy kolejne sztuki :

add_listi power_listpotrzebują dodatkowych argumentów, stąd użycie lambdafunkcji zewnętrznych.
Zarówno sorted_listi uniq_listdziałają bez dodatkowych argumentów. Zapakowanie ich w Partialklasy jest wystarczające.

Oto ostatni przykład:

>>> list_elements = [1,2,3,3,4]
>>> element_list = Pipe() | add_list(2) >> power_list(3) >> sorted_list >> uniq_list
>>> element_list(list_elements)
... [64, 27, 125, 216]

Wniosek

Jeśli dotarłeś tak daleko, bardzo dziękuję za cierpliwość i ciekawość.

To był dość zabawny eksperyment, aby przetestować niektóre ukryte funkcje, które widzimy w zaawansowanych narzędziach Pythona. Nieuchronnie skłaniają nas do pytania o zakres elegancji składni, jaką możemy osiągnąć.

Suggested posts

Nauka w tygodniu pracy ma większe znaczenie niż myślisz

Nauka w tygodniu pracy ma większe znaczenie niż myślisz

Często mamy trudności z wdrożeniem tego, co wiemy, że jest dla nas dobre. Od mówienia drugiej osobie, że ją kochamy, po pamiętanie, by mówić jak pirat, zawsze znajdą się tacy, którzy twierdzą, że dzień, tydzień lub miesiąc wydarzeń nie jest potrzebny, ponieważ już to robią.

Co możesz zrobić w swoim okresie oczekiwania (czekając na wylądowanie Twoja pierwsza praca w technologii)

Co możesz zrobić w swoim okresie oczekiwania (czekając na wylądowanie Twoja pierwsza praca w technologii)

Przejście do nowej kariery może być niezwykle trudne, jeśli spróbujesz zrobić to sam. Ważne jest, aby znaleźć odpowiedzialnych partnerów, którzy są na tym samym poziomie uczenia się co ty, którzy mają podobne cele, wytrwałość i motywację.

Related posts

zaimki są bardzo przerażające

Uderzyło mnie to nagle, jak to często bywa. Znowu jest w połowie <Nie, nie ten w Pacyfiku, bordowy, ten na karnawale> Każdy nagłówek jest głośny…..

Zabójstwo Jordana Neely'ego i problem „patriotycznego” rasizmu

Czy Stany Zjednoczone mogą zrobić zasadniczy krok, by nie utożsamiać zachowania rasistowskiego z byciem dobrym Amerykaninem?

Zabójstwo Jordana Neely'ego i problem „patriotycznego” rasizmu

[Ostrzeżenie: ten esej zawiera zrzuty ekranowe ludzi wychwalających mordercę Jordana Neely'ego.] Funkcjonariusze organów ścigania w końcu - i być może niechętnie - oskarżyli Daniela Penny'ego, człowieka, który dusił Jordana Neely'ego aż do śmierci, o to zabójstwo.

Zbieranie OSINT na potrzeby polowania na zagrożenia

Zbieranie OSINT na potrzeby polowania na zagrożenia

Hej, cyberentuzjaści! Witamy ponownie w serii OSINT poświęconej polowaniu na zagrożenia. W pierwszym artykule przedstawiłem przegląd OSINT i jego znaczenie w polowaniu na zagrożenia.

Finansowanie usuwania dwutlenku węgla w RO24

Podział wniosków o środki Carbon180 na różne ścieżki

Finansowanie usuwania dwutlenku węgla w RO24

Autor: Alyson Lee, doradca zarządzający ds. spraw rządowych Coroczny proces przyznawania środków przez rząd federalny ma kluczowe znaczenie dla naszych wysiłków na rzecz sfinansowania usuwania dwutlenku węgla (CDR). Każdego roku Carbon180 przesyła prośby do różnych biur kongresowych, aby pomóc wskazać, gdzie będą płynąć dolary w przyszłym roku.