fbpx

Cześć, witam Cię w szóstym już wpisie z serii „Kurs Python 3 by MR”. Nie było mnie pewien czas, pierwszy raz ilość tematów mnie przytłoczyła. Postanowiłem wrócić na pełen etat do pisania bloga kosztem mniejszych projektów. Jest to temat na osobny artykuł, więc dziś nie o tym! 

Dziś poruszę następujące tematy:

  • Czym są wyrażenia listowe, generujące i słownikowe?
  • Co to jest funkcja, jak ją budujemy i w jaki sposób używamy?

Po tym wpisie będziesz posiadać wszystkie niezbędne elementy programistycznego rzemiosła, by rozpocząć tworzyć własne aplikacje.

Koniec gadania. Zaczynajmy!


Kurs Python — wprowadzenie

Dzisiejszy wpis będzie niejako kontynuacją wpisu numer 50. W pierwszej kolejności przejdę do wyrażeń i postaram się w jednym akapicie wyjaśnić ich ideę.

Na wyrażenia składają się wyrażenia:

  • listowe
  • słownikowe
  • generujące

Dalej poruszę temat bardzo rozległy, czyli podstawy funkcji.

Jak widać, tematów dziś jest sporo, więc zabieramy się za naukę!

Wyrażenia

Człowiek jest taką istotą, że lubi sobie wszystko uprościć — niejako skrócić czas potrzebny, chociażby na pisanie kodu. Nie inaczej mamy w przypadku wyrażeń dostępnych w języku Python.

Wyobraź sobie zadanie, w którym musisz zapisać liczby parzyste w jednej liście, liczby nieparzyste natomiast w drugiej liście ze zbioru złożonego ze 100 elementów.

Pierwsze co nasuwa się na myśl to pętla, która przejdzie po każdej liczbie ze zbioru wejściowego, następnie sprawdzi, czy liczba dzieli się przed dwa bez zera i podejmie decyzję za pomocą instrukcji warunkowej, do której liczby przypisać.

Jak widzimy poniżej, kod nie jest skomplikowany, lecz wadą takiego rozwiązania jest jego objętość.

even = []
odd = []

for value in range(100):
    if value % 2 == 0:
        even.append(value)
    else:
        odd.append(value)

Wyrażenia listowe

Powyższy kod możemy skrócić do jednej linii, tworząc tak zwane wyrażenie listowe. Na początku odpowiemy sobie, czym takie wyrażenie jest.

Wyrażenie listowe to nic innego jak tworzenie listy w „zgrabny” sposób, na podstawie innej listy lub sekwencji. Tak samo, jak w powyższym kodzie, tak i w wyrażeniach używać będziemy pętli for oraz warunków (conditions).

Poniżej kod, który robi dokładnie to samo, co ten powyżej! Robi wrażenie?

even = [value for value in range(100) if value % 2 == 0]
odd = [value for value in range(100) if value % 2 != 0]

Omówimy teraz każdy z trzech elementów wyrażenia listowego. Na obrazie poniżej kolorem zielonym mamy zaprezentowane WYJŚCIE. Jak możesz zauważyć, dane wyjściowe mamy na początku wyrażenia, nie tak jak normalnie na końcu.

Drugim elementem jest WEJŚCIE. W to miejsce wstawiamy sekwencję lub listę. W naszym przypadku wystarczy funkcja RANGE, która wygeneruje nam listę z zakresu od — do.

Na końcu nieobowiązkowy WARUNEK. Dzięki niemu możemy sterować elementami, które mają pojawić się na wyjściu wyrażenia.

W drugim przykładzie na obrazku podnosimy każdą nieparzystą liczbę z zakresu od 1 do 100 do potęgi drugiej.

kurs python - opis budowy wyrażenia w języku Python 3

Wyrażenia generujące

Czas przejść do drugiego typu wyrażeń. Będą to wyrażenia generujące, które swoją budową nie odbiegają znacząco od omawianych wcześniej wyrażeń listowych. 

Zasadniczo jedyna różnica wizualna, to zamiana nawiasów kwadratowych na standardowe. Kod z przykładu wyżej będzie więc wyglądał następująco.

even = (value for value in range(100) if value % 2 == 0)
odd = (value for value in range(100) if value % 2 != 0)
Jaka jest więc różnica?

W przypadku wyrażeń listowych, obiekt, który dostajemy z generatora, od razu znajduje się w pamięci. W przypadku wyrażenia generującego jest zgoła odmiennie. Nie zajmujemy dużej ilości miejsca w pamięci od razu podczas wywołania wyrażenia. Jest to największa zaleta tego typu wyrażeń.

Zobaczmy przykład z funkcją PRINT, dzięki której sprawdzimy, co nasze obiekty zawierają oraz jakie mają rozmiary.

Widzimy, że dla wyrażeń listowych obiekty zajmują więcej miejsca. W przypadku wyrażeń generujących rozmiar nie ulega zmianie nawet przy zwiększeniu wejściowego obiektu.

import sys

even10 = [value for value in range(10) if value % 2 == 0]
even20 = [value for value in range(20) if value % 2 == 0]
print(even10)
print(even20)
print(sys.getsizeof(even10))
print(sys.getsizeof(even20))

# Wynik dla even10 = [0, 2, 4, 6, 8]
# Wynik dla even20 = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# Wynik dla sys.getsizeof(even10) = 120
# Wynik dla sys.getsizeof(even20) = 184

even10 = (value for value in range(10) if value % 2 == 0)
even20 = (value for value in range(20) if value % 2 == 0)
print(even10)
print(even20)
print(sys.getsizeof(even10))
print(sys.getsizeof(even20))

# Wynik dla even10 = <generator object <genexpr> at 0x7f42e0fe8cf0>
# Wynik dla even20 = <generator object <genexpr> at 0x7f42e0fe8cf0>
# Wynik dla sys.getsizeof(even10) = 112
# Wynik dla sys.getsizeof(even20) = 112

No dobrze, ale w jaki sposób teraz dobrać się do konkretnych wartości z takiego obiektu?

Najprostszym sposobem będzie użycie pętli for. 

even = (value for value in range(10) if value % 2 == 0)
 
for item in even:
    print(item)

# 0
# 2
# 4
# 6
# 8

Nie jest to jednak główną zaletą wyrażenia generującego. Poza wspomnianym rozmiarem, dużym plusem jest to, że możemy na nim wywołać przeróżne funkcje. Dla przykładu sumowanie wszystkich elementów z danego zbioru.

numbers = (value for value in range(10))

print(sum(numbers))

# 45

Wyrażenia słownikowe

Trzecie i ostatnie wyrażenie, które omówimy, to wyrażenie słownikowe. Inaczej nazywane formułą słownikową. Tak jak w dwóch poprzednich przypadkach, tak i tu wyrażenie posłuży nam do tego, by skrócić kod i pozbyć się niejako pętli.

I dokładnie tak samo, jak poprzednio, różnica w wyrażeniu wynika ze zmian nawiasów. W wyrażeniu słownikowym używamy klamer { }.

Skoro wyrażenie słownikowe, to musimy liczyć się z tym, że wyjściowym obiektem będzie zbiór danych uporządkowany za pomocą klucza i wartości. 

Dobrze będzie to widać na przykładzie poniżej. Stworzę listę words, z dowolnymi słowami. Następnie do obiektu length przepiszę te wartości, gdzie kluczem będzie słowo (item), wartością natomiast będzie długość słowa.

words = {"Test", "Programowanie", "Z", "Pasją", "Mateusz", "Rus"}
length = {
    item: len(item)
    for item in words
}

print(length)

#{'Programowanie': 13, 'Pasją': 5, 'Mateusz': 7, 'Test': 4, 'Rus': 3, 'Z': 1}

Nic nie stoi na przeszkodzie, by przetransformować jeden słownik w inny słownik. Do tego pomożemy sobie jeszcze warunkiem. Stworzę listę owoców i warzyw, gdzie kluczem będzie nazwa, natomiast wartością cena danego produktu.

Następnie za pomocą wyrażenia słownikowego wybiorę takie produkty, których cena przekracza 4 złote i nadam im rabat w wysokości 10%.

items = {"Jabłka": 3.48, "Banany": 4.99, "Awokado": 15.99, "Pomidory": 3.99, "Ogórki": 8.99}

itemsDiscount = {
    key: value * 0.9
    for key, value in items.items()
    if value > 4
}

print(itemsDiscount)

#{'Banany': 4.4910000000000005, 'Awokado': 14.391, 'Ogórki': 8.091000000000001}

Podsumowanie

Mimo drobnych różnic między każdym z trzech rodzajów wyrażeń mają one różne zastosowania. Jedne nadają się do pracy z wielkimi zbiorami danych, inne są elastyczne i pozwalają w prosty sposób zbudować zbiór danych bazujący na kluczach i wartościach.

W ramach ćwiczeń polecam Ci użycie wyrażeń z plikami. Spróbuj linia po linii analizować w dowolny sposób plik, sprawdź rozmiary obiektów i czasy ich wykonania. 

Drugim ćwiczeniem niech będzie zbudowanie listy dzięki wyrażeniu, która zawierać będzie liczby podzielne przez 4, lecz niepodzielne przez 3.

Wynikami koniecznie podziel się w komentarzu!

Funkcje

Bardzo wiele materiału dotyczącego Python już wspólnie przerobiliśmy. To dopiero przedsmak, bo doszliśmy do pewnego punktu granicznego. Czym byłyby języki programowania bez funkcji? Są one podstawowym elementem niemal każdego języka programowania i stanowią najważniejszy budulec każdego większego programu.

Nie zaskoczę Cię, gdy napiszę, że z funkcji już wspólnie korzystaliśmy. Zarówno funkcja PRINT, jak i chociażby LEN, to przykłady funkcji z podstawowej biblioteki Python, którą kiedyś dla nas stworzyli programiści pracujący nad rozwojem tego języka. Pojawia się jednak zasadnicze pytanie.

Czym dokładnie są funkcje?

Możemy sobie ją wyobrazić jako pewien fragment kodu, który raz napisany może być wywołany wielokrotnie. Zamiast kilkukrotnego pisania kodu odpowiadającego za otwarcie pliku, dopisanie do niego jakiegoś tekstu, a następnie zamknięcie pliku i zapisanie go w danej lokalizacji możemy stworzyć jedną funkcję, która po otrzymaniu określonych parametrów wejściowych za każdym razem będzie powtarzać wspomnianą operację na pliku.

Z matematycznego punktu widzenia pod pojęciem funkcji rozumiemy przekształcenie, które na podstawie wartości pewnej liczby argumentów zwraca wynik. 

Możemy więc powiedzieć, że funkcja może zwrócić jakiś wynik, jednak nie jest to wymagane. W przypadku zapisu do pliku nie zwrócimy żadnej wartości na koniec działania funkcji, lecz w przypadku funkcji sumującej dwie liczby podane na wejście, na wyjściu pojawi się wynik dodawania.

Brzmi skomplikowanie i bełkotliwie? 

Przejdźmy do praktyki i stwórzmy rzeczoną funkcję!

def firstFunction(text, fileName):
    f = open(fileName, "w+")
    f.write(text + "\r\n")
    f.close()

firstFunction("testowyText", "text.txt")

Patrząc od pierwszej linii, mamy tam słowo kluczowe def (od słowa definition, czyli definicja funkcji), które rozpoczyna funkcję, następnie jej nazwa i podane w nawiasie argumenty wejściowe. Wszystko kończymy dwukropkiem.

W kolejnych trzech liniach mamy ciało funkcji, które odpowiadają za otworzenie, zapis i zamknięcie pliku.

W ostatniej linii następuje wywołanie funkcji z argumentami — tekst zapisywany do pliku oraz nazwa pliku. Fajne, prawda?

Uwaga na koniec. Jeżeli plik „text.txt” nie będzie istniał, to z automatu zostanie on utworzony. 

Do funkcji w bardziej zaawansowanych przykładach wrócimy w kolejnym wpisie z tej serii.

kurs python - opis budowy funkcji w języku Python 3

Kurs Python — podsumowanie

Powróciłem po dłuższej przerwie i jedyne co mogę napisać, to przepraszam za nieobecność. Rozpocząłem ponowne pisanie na blogu właśnie od kursu Python, ponieważ dziesiątki osób o niego dopytywały. 

Przekroczyliśmy połowę serii i powoli zbliżamy się do końca. Nie oznacza to jednak przerwy w pisaniu podobnych serii, ale o tym niebawem!

Po dzisiejszym artykule w połączeniu z poprzednimi mamy już komplet programistycznych elementów, by tworzyć pierwsze, w pełni funkcjonalne oprogramowanie. 

Podejmiesz wyzwanie i stworzysz kalkulator, który będzie sumował, odejmował, mnożył i dzielił? Nie przejmuj się wyglądem, wystarczy aplikacja w konsoli. Pamiętaj, by skorzystać z nowo poznanego elementu, czyli funkcji!

W razie pytań i problemów jestem do dyspozycji — mailowo, jak i w komentarzach.

PS. Będę wdzięczny za komentarze pod tym postem!

PS2. Czeka też na Ciebie prezent. Wystarczy, że zapiszesz się na Newsletter poniżej!

PS3. Dołącz do naszej grupy na Facebook!

PS4. Dołącz do naszego serwera na Discord!

Subskrybuj

Zapisz się na Newsletter, odbierz NAGRODĘ w postaci e-booka z 10 omówionymi algorytmami pojawiającymi się w pytaniach podczas REKRUTACJI.

Dodatkowo otrzymuj co niedzielę informacje na temat nowych wpisów, wiadomości ze świata IT i matematyki oraz ciekawych wydarzeniach. Nie przegap i dołącz już dziś do 419 osób!.

Źródła

https://docs.python.org/3/

Autor

👨‍💻 .NET and Python programming passionate 🏦 Digtial Banking Solutions 🎓 Student 📊 Psychology 📚 Bookworm 🏠 Warsaw

2 komentarze

  1. „Drugim ćwiczeniem niech będzie zbudowanie listy dzięki wyrażeniu, która zawierać będzie liczby podzielne przez 4, lecz niepodzielne przez 3.”

    Rozwiązanie to:

    even = [value for value in range(100) if (value % 4 == 0) and (value % 3 != 0) ]

    Nie spotkałem się jeszcze z generatorami za pomocą wyrażneń listowych. Fajnie że o tym napisałeś, Mateusz.

    Kiedyś pisałem sobie projekt na GitHub w którym chciałem potworzyć kalkulatory (konsolowy, okienkowy, webowy itp.).
    Doszedłem na razie tylko do konsolowego jednak może kiedyś wrócę do tego projektu.

    Tutaj jest link: https://github.com/eccololo/calculators

    Dzięki za fajny artykuł. Będę czekał na więcej :-).

    Cześć.

Napisz komentarz

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.

Dołącz do naszego serwera Discord i rozmawiaj o programowaniu!

X