• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

OOP, tworzenie klas z długich funkcji

Object Storage Arubacloud
0 głosów
182 wizyt
pytanie zadane 18 lipca 2019 w Python przez RafalS VIP (122,820 p.)

Ostatnio piszę w pracy sporo skryptów do command-line'owego użycia i denerwowało mnie żmudne deklarowanie argparserów. Napisałem, więc skrypt do generowania argparsera na podstawie docstringa i adnotacji typów funkcji.

Funkcja mi się trochę rozbudowała i pasowałoby połączyć funkcje z danymi jakąś klasą. Jaki interfejs powinna mieć ta klasa?

Czy obiekt per funkcja do przetworzenia to dobry design:

ArgparserGenerator(foo).generate()
ArgparserGenerator(bar).generate()

czy lepszy jest reużywalny obiekt:

argparser_generator = ArgparserGenerator()
argparser_generator.generate(foo)
argparser_generator.generate(bar)

Czy może tworzyć obiekt per funkcje, ale klasę schować w funkcji jako szczegół implementacyjny:

def generate_argparser(func):
    return ArgparserGenerator(foo).generate()

 

1 odpowiedź

+2 głosów
odpowiedź 18 lipca 2019 przez adrian17 Ekspert (344,860 p.)
wybrane 19 lipca 2019 przez RafalS
 
Najlepsza

A po co w ogóle klasa?

Czemu nie po prostu:

parser = generate_parser(foo)

Albo nawet, zakładając że zazwyczaj jego jedynym użyciem wygenerowanego argparsera będzie wywołanie na nim `.parse_args()`, to nawet

args = parse_args_from(foo)

Ostatnio piszę w pracy sporo skryptów do command-line'owego użycia i denerwowało mnie żmudne deklarowanie argparserów

Jeśli robisz to dla pracy, to raczej lepszym zużyciem zasobów czasowych będzie użycie gotowej biblioteki robiącej to, co chcesz - bo jest ich masa.

https://gist.github.com/supposedly/01224262b816df21b601ab0784d5f999

(btw, wygląda że `docopt` w zasadzie zrobił to samo, co zaproponowałem)

komentarz 18 lipca 2019 przez adrian17 Ekspert (344,860 p.)
(plus osobista opinia: generowanie z docstringa wydaje się trochę dziwne, bo nie wyobrażam sobie by dało się tam zreprodukować wszystkie ficzery argparse'a.)
komentarz 18 lipca 2019 przez adrian17 Ekspert (344,860 p.)

Jeszcze tylko dodam:

ArgparserGenerator(foo).generate()

To byłby raczej kandydat na refactor z klasy na funkcję, a nie na odwrót ;)

komentarz 18 lipca 2019 przez RafalS VIP (122,820 p.)

A po co w ogóle klasa?

Bo główna funkcja ma ~80 linijek i chciałem to jakoś pogrupować, a rozbijanie na małe funkcje bez klasy to znowu straszne programowanie proceduralne z przesyłaniem masy argumentów. A po to jest właśnie programowanie obiektowe żeby połączyć dane z funkcjami.

by dało się tam zreprodukować wszystkie ficzery argparse

Bo nie potrzebuje ich wszystkich, to ma uprościć żmudne przeklepywanie, help="", type="", required=False i action='store_true' dla booli.

A na dobrą sprawę wystarczy dodać dict jako drugi opcjonalny argument i można umożliwić dowolne dodatkowe/nadpisujące argumenty do add_argument, przez co jestem w stanie większość ficzerów wykorzystać.

Jeśli robisz to dla pracy, to raczej lepszym zużyciem zasobów czasowych

Nadarzyła się żadka okazja napisania czegoś ciekawszego w pythonie, a że naklepanie tego to pare godzin, więc skorzystałem.

komentarz 18 lipca 2019 przez RafalS VIP (122,820 p.)
Przyglądnę się jeszcze porządniej tej liście narzędzi, ale np taki docopt robi coś troszkę innego. Ja chcę mieć docstringi w kodzie i jednocześnie to samo w helpie skryptu jako command-line'owego toola.
komentarz 18 lipca 2019 przez adrian17 Ekspert (344,860 p.)

Bo główna funkcja ma ~80 linijek

To nie jest aż tak długie. Na przykład pylint domyślnie zaczyna narzekać przy ponad 100 statementach w funkcji. Wyrzucić może parę małych funkcji pomocniczych na bok i będzie fajnie.

to znowu straszne programowanie proceduralne z przesyłaniem masy argumentów

Dla jednych to jest straszne, dla innych niepotrzebne OOP jest straszne. Python z założenia jest językiem wieloparadygmatowym, nie ma tu aż takiego nacisku na OOP ;)

No i jeszcze jedno: wewnętrzna organizacja kodu nie powinna dyktować zewnętrznego API. Jak jakiś inny "zewnętrzny" user zapyta dlaczego musi robić `ArgparserGenerator(foo).generate()` zamiast bezpośredniego `generate_argparse(foo)` i usłyszy że to żeby "nie przekazywać wewnątrz masy argumentów", to podrapie się po głowie.

komentarz 19 lipca 2019 przez RafalS VIP (122,820 p.)

wewnętrzna organizacja kodu nie powinna dyktować zewnętrznego API

Dlatego myślałem o ukryciu tej klasy w funkcji.

Dzięki za rady, zobaczę ile da sie wyciągnąć.

A co myślisz o takim patternie:

Funkcja generate_argparse, która robi tylko pare asercji i wywołuje _generate_argparse którą zajmuję sie prawdziwym generowaniem?

komentarz 19 lipca 2019 przez adrian17 Ekspert (344,860 p.)

Funkcja generate_argparse, która robi tylko pare asercji i wywołuje _generate_argparse którą zajmuję sie prawdziwym generowaniem?

Brzmi OK.

Podobne pytania

0 głosów
3 odpowiedzi 393 wizyt
pytanie zadane 16 stycznia 2019 w Python przez niezalogowany
0 głosów
0 odpowiedzi 284 wizyt

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...