# Python 10 (flet cd., class)

# Python 10 (flet cd., class)
Photo by Mitchell Luo / Unsplash
  1. Powtórka flet
# Usuwanie wpisów z listy

import flet

def main(page: flet.Page):    #Funkcja main przyjmuje argument page, który reprezentuje okno/stronę aplikacji.
    page.title = "Dodaj zadania"

    pole_do_wprowadzenia = flet.TextField(label="Dodaj element")
    lista_elementow = flet.ListView() #ListView – widok listy, do którego będą dodawane kolejne elementy (wiersze)

    def dodaj(_e):  #Funkcja dodaj wywołuje się po kliknięciu przycisku „Dodaj”. _e to argument zdarzenia kliknięcia
        if pole_do_wprowadzenia.value: #Sprawdzamy, czy pole tekstowe nie jest puste

            def usun_wiersz(_e): #Definiowana wewnątrz dodaj. Pozwala usunąć konkretny wiersz z listy (lista_elementow).page.update() odświeża widok, żeby zmiany były widoczne
                lista_elementow.controls.remove(wiersz)
                page.update()

            wprowadzone = flet.Text(pole_do_wprowadzenia.value)
            przycisk = flet.FilledButton("Usuń", on_click=usun_wiersz)
            wiersz = flet.Row([wprowadzone, przycisk]) #Text – wyświetla wpisany tekst (treść zadania). FilledButton("Usuń") – przycisk do kasowania danego wiersza. Row – kontener w poziomie, łączący tekst i przycisk w jednym wierszu.

            lista_elementow.controls.append(wiersz)
            pole_do_wprowadzenia.value = ""
            page.update() #Wiersz trafia do listy ListView. Pole tekstowe zostaje wyczyszczone. Widok strony się odświeża.

    przycisk = flet.FilledButton("Dodaj", on_click=dodaj) #Tworzymy przycisk „Dodaj”, który wywołuje funkcję dodaj

    page.add(pole_do_wprowadzenia, przycisk, lista_elementow)# Dodajemy do strony: pole tekstowe, przycisk i listę.

flet.app(target=main)
# Aplikacja do generowania kodów QR

import flet
import qrcode
from io import BytesIO
import base64


def main(page: flet.Page):
    page.title = "Generator kodów QR"
    page.theme_mode = flet.ThemeMode.LIGHT
    page.padding = 10

    def utworz_qr_image(text_data: str) -> str:
        img = qrcode.make(text_data)
        buffer = BytesIO()
        img.save(buffer)
        qr_img_b64 = base64.b64encode(buffer.getvalue()).decode()
        # encode koduje znaki w buforze z pomocą base64
        # decode zamienienia dane binarne na tekst
        return qr_img_b64

    def wyswietl_qr(_e):
        if do_zakodowania.value:
            obrazek_jako_tekst = utworz_qr_image(do_zakodowania.value)
            obrazek.src_base64= obrazek_jako_tekst
            page.add(obrazek)
            page.update()

    do_zakodowania = flet.TextField(
        width=400, text_align=flet.TextAlign.RIGHT, label="tekst do zakodowania qr"
    )
    generuj_przycisk = flet.FilledButton(text="Generuj", on_click=wyswietl_qr)
    obrazek = flet.Image(src_base64="")

    page.add(do_zakodowania, generuj_przycisk)


flet.app(main)

Class

W Pythonie klasy to sposób definiowania własnych typów obiektów. Umożliwiają one łączenie danych (atrybutów) oraz funkcji (metod) w jedną spójną całość. Dzięki temu można pisać kod w stylu obiektowym, który jest bardziej uporządkowany, wielokrotnego użytku i łatwiejszy w rozbudowie. Uwaga - nie przyspieszają działania aplikacji.

nie mylić: KLASA to nie jest OBIEKT !!
  • Klasa to „szablon” lub „przepis”, który opisuje, jak tworzyć obiekty — czyli konkretne egzemplarze tego szablonu.
          • np. to ogólny opis kota
  • Obiekt to pojedyncza realizacja, zawierająca konkretne dane i zachowania.
          • np. to opis rudego kota sąsiada (konkretny przypadek)
  • Po co korzystamy z klas?
    • klasy przydatne są, kiedy chcemy unikać powtórzeń
    • podejście obiektowe ułatwia pracę w zespole i dzielenie zadań w projekcie
DOBRA PRAKTYKA: Nazwy klas zaczynamy z dużej litery
class PostacGracza:
    def __init__(
        self,
        imie: str,
        hp: int = 100,
        mana: int = 100,
        wytrzymalosc = 100,        
    ):
        self.imie = imie
        self.hp = hp
        self.mana = mana
        self.wytrzymalosc = wytrzymalosc
    
    def zadaj_obrazenie(self, ilosc_obrazen: int):
        self.hp -= ilosc_obrazen
        if self.hp <=0:
            print("Gracz martwy!")
 
class Mag(PostacGracza):
    def __init__(
        self,
        imie: str,
        mana: int = 200,
    ):
        super().__init__(imie=imie, mana=mana)


class Wojownik(PostacGracza):
    def __init__(
        self,
        imie: str,
        wytrzymalosc: int = 200,
    ):
        super().__init__(imie=imie, wytrzymalosc=wytrzymalosc)


gracz1 = Mag("Fizban")
print(gracz1.imie, gracz1.hp, gracz1.mana)
print(type(gracz1)) 

gracz2 = Wojownik("Caramon")
print(gracz2.imie, gracz2.hp, gracz2.mana, gracz2.wytrzymalosc) 
print(type(gracz2))

Ważne aspekty konstruktora (__init__):

  • self to referencja do aktualnej instancji obiektu
    Co to znaczy: self to sposób, w jaki obiekt odnosi się do samego siebie.
  • Konstruktor może mieć parametry domyślne (Możemy ustawić wartości "na wszelki wypadek", jeśli ktoś nie poda wszystkich informacji).
  • Można wykonać walidację danych przed przypisaniem (Możemy sprawdzić, czy podane dane są poprawne, zanim je zapiszemy).
class Osoba:
    def __init__(self, imie, wiek):
        if wiek < 0:
            print("BŁĄD! Wiek nie może być ujemny!")
            return
        if len(imie) == 0:
            print("BŁĄD! Imię nie może być puste!")
            return
            
        self.imie = imie
        self.wiek = wiek

osoba1 = Osoba("Anna", 25)    # OK
osoba2 = Osoba("", -5)        # Błędy - nie utworzy się
  • __init__ NIE zwraca wartości (Konstruktor tylko przygotowuje obiekt, ale go nie "oddaje" - Python robi to automatycznie).
class Kot:
    def __init__(self, imie):
        self.imie = imie
        # NIE PISZ: return self  <- To jest błędne!
        # NIE PISZ: return "cokolwiek"  <- To też!

# Python automatycznie zwraca gotowy obiekt:
moj_kot = Kot("Mruczek")  # moj_kot to gotowy obiekt kota

Wpływ klas na wydajność aplikacji

Klasy same w sobie NIE przyspieszają aplikacji - wręcz przeciwnie, mogą ją nieznacznie spowolnić przez:

  • Dodatkowy narzut na tworzenie obiektów
  • Przechowywanie metadanych klasy
  • Mechanizm dziedziczenia i rozwiązywania nazw metod