Programuję w Pythonie od około dwóch lat; głównie dane (pandy, mpl, numpy), ale także skrypty automatyzacji i małe aplikacje internetowe. Staram się zostać lepszym programistą i poszerzyć swoją wiedzę o Pythonie, a jedną z rzeczy, która mnie niepokoi, jest to, że nigdy nie korzystałem z klasy (poza kopiowaniem losowego kodu kolby dla małych aplikacji internetowych). Ogólnie rozumiem, czym one są, ale nie potrafię zrozumieć, dlaczego potrzebowałbym ich zamiast prostej funkcji.
Aby dodać szczegółowości do mojego pytania: piszę mnóstwo zautomatyzowanych raportów, które zawsze obejmują pobieranie danych z wielu źródeł danych (mongo, sql, postgres, apis), przeprowadzanie dużej lub małej ilości danych i formatowanie, zapisywanie danych do csv / excel / html, wyślij go w e-mailu. Skrypty obejmują od ~ 250 do ~ 600 linii. Czy byłby jakiś powód, dla którego miałbym używać klas do tego i dlaczego?
Odpowiedzi:
Klasy są filarem programowania obiektowego . OOP jest bardzo zainteresowany organizacją kodu, możliwością ponownego użycia i hermetyzacją.
Po pierwsze, zastrzeżenie: OOP jest częściowo w przeciwieństwie do programowania funkcjonalnego , które jest innym paradygmatem często używanym w Pythonie. Nie każdy, kto programuje w Pythonie (a na pewno w większości języków) używa OOP. W Javie 8 można wiele zrobić, ale nie jest zorientowane obiektowo. Jeśli nie chcesz korzystać z OOP, nie rób tego. Jeśli piszesz tylko jednorazowe skrypty do przetwarzania danych, których nigdy więcej nie użyjesz, pisz dalej tak, jak jesteś.
Istnieje jednak wiele powodów, dla których warto używać OOP.
Niektóre powody:
Organizacja: OOP definiuje dobrze znane i standardowe sposoby opisywania i definiowania zarówno danych, jak i procedur w kodzie. Zarówno dane, jak i procedura mogą być przechowywane na różnych poziomach definicji (w różnych klasach) i istnieją standardowe sposoby mówienia o tych definicjach. Oznacza to, że jeśli używasz OOP w standardowy sposób, pomoże to Tobie i innym później zrozumieć, edytować i używać Twojego kodu. Ponadto, zamiast używać złożonego, arbitralnego mechanizmu przechowywania danych (dykty dyktowania lub listy, dykty lub listy dykt zbiorów itp.), Możesz nazwać fragmenty struktur danych i wygodnie się do nich odwoływać.
Stan: OOP pomaga definiować i śledzić stan. Na przykład w klasycznym przykładzie, jeśli tworzysz program, który przetwarza uczniów (na przykład program ocen), możesz przechowywać wszystkie potrzebne informacje o nich w jednym miejscu (imię i nazwisko, wiek, płeć, poziom kursy, oceny, nauczyciele, rówieśnicy, dieta, specjalne potrzeby itp.), a dane te są przechowywane tak długo, jak długo obiekt żyje i jest łatwo dostępny.
Hermetyzacja : w przypadku hermetyzacji procedura i dane są przechowywane razem. Metody (termin OOP dla funkcji) są zdefiniowane wraz z danymi, na których działają i które generują. W języku takim jak Java, który umożliwia kontrolę dostępu , lub w Pythonie, w zależności od tego, jak opisujesz swój publiczny interfejs API, oznacza to, że metody i dane mogą być ukryte przed użytkownikiem. Oznacza to, że jeśli potrzebujesz lub chcesz zmienić kod, możesz zrobić wszystko, co chcesz, z implementacją kodu, ale zachowaj te same publiczne interfejsy API.
Dziedziczenie : Dziedziczenie umożliwia zdefiniowanie danych i procedur w jednym miejscu (w jednej klasie), a następnie zastąpienie lub rozszerzenie tej funkcjonalności później. Na przykład w Pythonie często widzę ludzi tworzących podklasy
dict
klasy w celu dodania dodatkowej funkcjonalności. Typowa zmiana polega na nadpisaniu metody, która zgłasza wyjątek, gdy żądany jest klucz ze słownika, który nie istnieje, w celu podania wartości domyślnej na podstawie nieznanego klucza. Pozwala to na rozszerzenie własnego kodu teraz lub później, zezwolenie innym na rozszerzenie Twojego kodu i pozwala na rozszerzenie kodu innych osób.Wielokrotne wykorzystanie: wszystkie te i inne powody pozwalają na większe możliwości ponownego wykorzystania kodu. Kod zorientowany obiektowo umożliwia jednorazowe napisanie solidnego (przetestowanego) kodu, a następnie jego wielokrotne używanie. Jeśli potrzebujesz dostosować coś do swojego konkretnego przypadku użycia, możesz dziedziczyć z istniejącej klasy i nadpisać istniejące zachowanie. Jeśli chcesz coś zmienić, możesz to wszystko zmienić, zachowując istniejące sygnatury metod publicznych i nikt nie jest mądrzejszy (miejmy nadzieję).
Ponownie, istnieje kilka powodów, aby nie używać OOP i nie musisz tego robić. Ale na szczęście w przypadku języka takiego jak Python, możesz używać tylko trochę lub dużo, to zależy od Ciebie.
Przykład użycia studenta (brak gwarancji jakości kodu, tylko przykład):
Zorientowany obiektowo
Standardowy dykt
źródło
Ilekroć musisz utrzymać stan swoich funkcji i nie można tego osiągnąć za pomocą generatorów (funkcji, które dają, a nie zwracają). Generatory zachowują swój własny stan.
Jeśli chcesz przesłonić którykolwiek ze standardowych operatorów, potrzebujesz klasy.
Zawsze, gdy używasz wzorca Visitor, będziesz potrzebować klas. Każdy inny wzorzec projektowy można osiągnąć bardziej efektywnie i czysto za pomocą generatorów, menedżerów kontekstu (które są również lepiej implementowane jako generatory niż jako klasy) i typów POD (słowniki, listy i krotki itp.).
Jeśli chcesz napisać kod „pythonowy”, powinieneś preferować menedżery kontekstu i generatory od klas. Będzie czystszy.
Jeśli chcesz rozszerzyć funkcjonalność, prawie zawsze będziesz w stanie to osiągnąć poprzez zawieranie, a nie dziedziczenie.
Jak każda zasada ma wyjątek. Jeśli chcesz szybko hermetyzować funkcjonalność (tj. Napisać kod testowy zamiast kodu wielokrotnego użytku na poziomie biblioteki), możesz hermetyzować stan w klasie. Będzie to proste i nie będzie wymagało wielokrotnego użytku.
Jeśli potrzebujesz destruktora w stylu C ++ (RIIA), zdecydowanie NIE chcesz używać klas. Chcesz menedżerów kontekstu.
źródło
Generator
instancji (specjalnego iteratora), podczas gdy zamknięcia mogą mieć dowolny podpis. Zasadniczo możesz uniknąć zajęć przez większość czasu, tworząc domknięcia. A domknięcia to nie tylko „funkcje zdefiniowane w kontekście innych funkcji”.Myślę, że robisz to dobrze. Zajęcia są rozsądne, gdy trzeba symulować jakąś logikę biznesową lub trudne rzeczywiste procesy z trudnymi relacjami. Jako przykład:
Proponuję również obejrzenie tego klasycznego wideo
źródło
Klasa definiuje byt ze świata rzeczywistego. Jeśli pracujesz nad czymś, co istnieje indywidualnie i ma własną logikę, która jest odrębna od innych, powinieneś utworzyć dla tego klasę. Na przykład klasa, która hermetyzuje łączność z bazą danych.
Jeśli tak nie jest, nie ma potrzeby tworzenia klasy
źródło
To zależy od Twojego pomysłu i projektu. jeśli jesteś dobrym projektantem, to OOP wyjdą naturalnie w postaci różnych wzorców projektowych. W przypadku prostego skryptu przetwarzanie OOP może być narzutem. Po prostu rozważ podstawowe zalety OOP, takie jak wielokrotnego użytku i rozszerzalne, i upewnij się, czy są potrzebne, czy nie. OOP sprawiają, że złożone rzeczy stają się prostsze, a prostsze - złożone. Po prostu utrzymuje rzeczy w prosty sposób w dowolny sposób, używając OOP lub nie używając OOP. co jest prostsze, użyj tego.
źródło