TL;DR: Zaczynam wprowadzać klasy do projektu, tak jak to zapowiadałem. Do czego są klasy i dlaczego warto je mieć? Fajnie tłumaczy to TheNewBoston. Klasa to po prostu zgrupowanie podobnych funkcji i zmiennych, które będą wielokrotnie wspólnie używane.

Potworność potwora

Wyobraź sobie, że tworzysz grę komputerową z Potworami (Enemies). Każdy potwór ma podobne cechy. Ma określoną liczbę życia, które traci gdy go zaatakujesz. Zamiast za każdym razem kiedy tworzysz nowego potwora przekopiowywać i ręcznie modyfikować jego funkcje czy zmienne (szczególnie, gdy już się tego trochę nazbierało), mamy swego rodzaju szablon – klasę, którą możemy wykorzystać wielokrotnie.

Klasa dla inputu

Myślę, że w moim przypadku dobrze by było mieć w klasie wszystkie funkcje, które będą działać na inpucie użytkownika. Obecnie pojedyncze funkcje mam porozrzucane w różnych miejscach.

Np. w momencie dodawania entry/inputu przez użytkownika, program próbuje przerobić go na liczbę.

def add_entry(evt):  # For calculation button
    global total_info, entries
    entry = top_frame_input.get()
    entry = entry.replace("+", "")

    try:
        int(entry)
        # entries_list.insert(0,entry)
        entries.append(int(entry))
        total_info = "Total: " + str(sum(entries))
        status.set(total_info)
        entries_update()
        top_frame_input.delete(0, END)

    except:
        top_frame_input.focus()

W innym miejscu, gdy entry ma być przekonwertowane na format HH:MM:SS i wrzucone na listbox, działania na nim są robione w innej funkcji:

def entries_update():
    entries_list.delete(0, END)
    for sec in entries:
        converted_seconds = "%d:%02d:%02d" % (sec / 3600, sec / 60 % 60, sec % 60) # convert to HH:MM:SS
        entries_list.insert(0, converted_seconds)

Wszystko w jednym miejscu

Chciałbym, żeby wszystkie możliwe działania były wykonywane w jednym miejscu – w klasie a gotowy, przerobiony wedle potrzeb input był przez nią ładnie wypluwany.

Zanim zacznę mieszać w kodzie, który może się widowiskowo wykrzaczyć warto przypomnieć sobie jak cudowny jest GIT. Stworzę nowy branch i na nim będę działać.

> git branch withclass

>> git checkout withclass

Pięknie. Teraz można psuć.

…kilka godzin później

Działać, działa

Stworzyłem klasę Entry. Działa w takim sensie, że praktycznie wszystko pozostało bez zmian. Oto jak wygląda moja nowa klasa:

class Entry:

    def __init__(self):
        self.input = top_frame_input.get()
        self.cleaner()
        self.seconds = int(self.input)
        self.add()
        self.update()
        status.set(self.sum())
        print(self.seconds)
        print(self.converter(self.seconds))

    def cleaner(self):
        self.input = re.sub("[^0-9:]", "", self.input) # leaves only digits and ":" into input
        try:
            h,m,s = re.split(':',self.input)
            self.input = int(datetime.timedelta(hours=int(h),minutes=int(m),seconds=int(s)).total_seconds())
        except:
            self.input = re.sub("\D", "", self.input) # clean input from non-digit characters

        # self.input = self.input.replace("+", "") # simplest method (replace just one character)
            # in case this one above will make a troubles

    def converter(self, sec):
        convertion = "%d:%02d:%02d" % (sec / 3600, sec / 60 % 60, sec % 60)  # convert to HH:MM:SS
        return convertion

    def add(self):
        global entries
        entries.append(self.seconds)
        print("Entries: "+str(entries))

    def sum(self):
        global total_info
        total = sum(entries)
        return total

    def update(self):
        entries_list.delete(0, END)
        for e in entries:
            converted_entry = self.converter(e)
            entries_list.insert(0, converted_entry)

Najważniejsze, że klasa nie wykrzacza wszystkiego. Cały kod jest teraz trochę namerdany więc nie będę go wrzucać, zrobię to jak go lekko posprzątam. Mózg paruje, więc na razie tak musi zostać.

Co ważne, przy okazji udało się dodać dwie funkcjonalności:

Użytkownik może już wprowadzić czas w formacie HH:MM:SS

Można teraz wprowadzić liczbę sekund albo czas w formacie HH:MM:SS. Program „rozpoznaje” format a wszelkie inne znaki, które nie są cyframi lub „:” kasuje. Udało mi się to osiągnąć dzięki modułowi re, który trzeba zaimportować. A konkretniej dzięki:

self.input = re.sub("[^0-9:]", "", self.input)

To jakże superanckie rozwiązanie znalazłem tutaj.

„[^0-9:]” oznacza, że pozostawia cyfry od 0 do 9 oraz „:”. Jeśli natomiast chcesz wywalić wszystko co nie jest liczbą można dać  „\D”. Dodatkowe info i inne opcje można znaleźć tu.

Konwersja z formatu HH:MM:SS z powrotem na liczbę sekund.

Jest to o tyle ważne, że jeśli użytkownik wprowadzi dane w tym formacie to mają być one zapisane jako liczba sekund.

h,m,s = re.split(':',self.input)
self.input = int(datetime.timedelta(hours=int(h),minutes=int(m),seconds=int(s)).total_seconds())

To rozwiązanie znalazłem tutaj.  Mamy tu połączenie dwóch rzeczy. Modułu re oraz datetime (oba trzeba zaimportować). Gdzie:

re.split – rozróżnia liczby oddzielone „:”

.total_seconds() – wyciąga liczbę sekund

 

To tyle móżdżenia na dziś. Chaos w głowie, chaos w kodzie i chaos w poście. Wszelkie uwagi więcej niż mile widziane!

 

2 uwagi do wpisu “Koślawe, ale działa – wprowadzenie klasy do projektu

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj /  Zmień )

Zdjęcie na Google

Komentujesz korzystając z konta Google. Wyloguj /  Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj /  Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj /  Zmień )

Połączenie z %s