Python - wprowadzenie

02 - Zmienne i proste obliczenia

Pierwsze kroki

Otwórz terminal, w terminalu wpisz anaconda-navigator, wybierz JupyterLab (lub uruchom wg. instrukcji z poprzedniej lekcji). W panelu po prawej stronie pojawi się dokument Untitled.ipynb, jeśli pojawi się okienko z pytaniem o kernel (“Select Kernel”) to wybierz Python 3.

Zapisz dokument (“Notebook”) jako Pierwsze_kroki.ipynb wybierając w menu File->Save Notebook As... lub użyj skrótu klawiszowego Ctrl+Shift+S. Katalog, w którym zapiszesz plik wybierz wcześniej w lewym panelu.

W otwartym dokumencie widać szary pasek poprzedzony znakami []:. Kliknij w szarym pasku i wpisz pierwsze poniższe polecenie, a następnie wciśnij Shift+Enter:

print("Witaj Świecie!")
Witaj Świecie!

Jak widać, w wyniku wykonania komendy pojawił się napis Witaj Świecie a także nowe pole, w którym możemy wpisać kolejną komendę.

Polecenie print() odpowiada (w tym przykładzie) za wypisanie tekstu, który umieszczamy w parze nawiasów towarzyszącej poleceniu oraz dodatkowo w cudzysłowach. Teraz wpisz i wykonaj (Shift+Enter) następne polecenie:

tekst = "Witaj Świecie!"

Tym razem nie widać żadnego efektu. Wykonaj zatem kolejne polecenie:

print(tekst)
Witaj Świecie!

Porównaj pierwszą komendę z ostatnią. Różnią się, choć wynik jest taki sam. W pierwszej, przekazaliśmy poleceniu print() bezpośrednio tekst, który następnie został wydrukowany. Drugiej przekazaliśmy słowo tekst. Właściwie powinienem napisać nie “słowo”, ale zmienną. Zmienna ma swoją nazwę, w tym przypadku tekst. Możemy jej przypisać jakąś wartość, którą następnie przechowuje. W tym przypadku był to krótki tekst, ale możliwości jest więcej o czym będzie mowa dalej. Przypisanie wartości zmiennej odbyło się przy użyciu operatora =. Z obu stron operatora znajdują się spacje, nie jest to konieczne, ale zwiększa czytelność kodu.

W powyższym przykładzie do zmiennej tekst przypisaliśmy wcześniej tekst “Witaj Świecie!”. Następnie zmienną przekazaliśmy poleceniu print(), które wydrukowało przechowywany w niej tekst na ekranie.

Można jednak zadać sobie pytanie, skąd polecenie print() “wiedziało”, że nie powinno wydrukować tekstu “tekst”, tylko użyć zmiennej o nazwie tekst. Uruchom kolejne polecenie:

print("tekst")
tekst

Tym razem najwyraźniej polecenie nie użyło zmiennej tekst. Porównaj powyższe polecenia. Gdy przekazany poleceniu print() tekst znajdował się w cudzysłowach, był on drukowany tak, jak został wpisany. Kiedy użyliśmy zmiennej, została ona wpisana bez cudzysłowów. Spróbuj uruchomić kolejne polecenie:

print(Witaj Świecie!)
  File "<ipython-input-12-aebb45e2da23>", line 1
    print(Witaj Świecie!)
                      ^
SyntaxError: invalid syntax

Tym razem nie został wydrukowany tekst ale pojawił się komunikat o błędzie. SyntaxError: invalid syntax oznacza błąd składni, w tym przypadku, rzecz jasna, pominięte zostały cudzysłowy.

Warto w tym miejscu zauważyć, że polecenie print() jest tak naprawdę wywołaniem funkcji o tej nazwie. Funkcje będziemy omawiać później, na razie warto wiedzieć, że są to pewne fragmenty kodu, które mają swoją nazwę. Możemy im przekazywać dane, które mogą być w funkcjach przetwarzane, funkcje mogą również zwracać dane.

Liczby i proste obliczenia

Sprawdźmy, jak polecenie print() zareaguje na wprowadzenie liczby, zamiast tekstu, czy zmiennej.

print(7)
7

Liczba (wprowadzona bez cudzysłowów) została prawidłowo wydrukowana. Teraz spróbujmy czegoś innego:

print(7+3)
10

Jak widać obie liczby zostały do siebie dodane, a wynik został wydrukowany.

Powyżej użyliśmy polecenia print(), ale jeśli zależy nam po prostu na uzyskaniu wyniku, można działanie Teraz sprawdźmy inne działania:

print(7-3)
print(7*3)
print(7**3)
print(7/3)
print(7//3)
print(7%3)
4
21
343
2.3333333333333335
2
1

Podsumujmy poznane operatory arytmetyczne:

Operator znaczenie przykład wynik
+ dodawanie 7+3 10
- odejmowanie 7-3 4
* mnożenie 7*3 21
** potęgowanie 7**3 343
/ dzielenie 7/3 2.33…
// dzielenie całkowite 7//3 2
% reszta z dzielenia 7%3 1

Jeśli pracujemy w JupyterLab, IPython czy Pythonie w trybie interaktywnym (zob. poniżej) i chcemy zobaczyć wynik działania, to nie musimy używać polecenia print() o ile jest to pojedyncze albo ostatnie wyrażenie w ciągu poleceń. Wystarczy wpisać bezpośrednio działanie i wynik się wyświetli:

print(7*7)
2*2
49
4

Metoda ta jednak nie zadziała, jeśli użyjemy jej pisząc skrypt, czym zajmiemy się później.

Zmienne i liczby

Poprzednio użyliśmy zmiennej do przechowania krótkiego tekstu. Teraz w zmiennych przechowamy liczby i użyjemy ich w obliczeniach:

x = 11
y = 123
print(x)
print(x * y)
11
1353

Wynik obliczeń można także przechować w zmiennej:

z = x * y
print(z)
1353

Zmienne, jak sama nazwa wskazuje, są zmienne, co oznacza, że można zmienić przypisane im wartości:

x = 2
z = y**2
print(x)
print(z)
2
15129

Zanim przejdziemy dalej, warto zwrócić uwagę na pewną bardzo istotną cechę Pythona. Zmienne są jedynie nazwami, które wskazują na obiekt przechowywany w pamięci komputera. Zatem przypisywanie im wartości nie polega na tworzeniu kopii tej wartości ale jedynie ,,przypinaniem etykietki’’, którą jest zmienna. Poźniej wyjaśnię dokładniej czym jest obiekt, na razie przymijmy, że jest to ,,coś’’ co może przechowywać dane (np. liczby) i wykonywać zdefiniowane operacje.

Przyjrzyjmy się następującej serii poleceń:

x = 20
print(x)
y = x
print(y)
x = 10
print(x)
print(y)
20
20
10
20

Kolejno zostały wykonane następujące czynności:

  1. Utworzono obiekt przechowujący wartość 20 a następnie została utworzona ,,etykietka’’ (zmienna) o nazwie x wskazująca na ten obiekt.
  2. Wydrukowano wartość przechowywaną w obiekcie wskazywanym przez zmienną x.
  3. Utworzono kolejną zmienną y wskazującą na ten sam obiekt (przechowujący wartość 20).
  4. Wydrukowano wartość przechowywaną w obiekcie wskazywanym przez zmienną y.
  5. Utworzono kolejny obiekt przechowujący liczbę 10 i przypisano zmienną x do tego obiektu.
  6. Wydrukowano wartości przechowywane przez obiekty, do których zostały przypisane obie zmienne.

Jak widać nie zmieniła się wartość, która została zwrócona po powtórnym przywołaniu zmiennej y.

Dalej, dla uproszczenia, będę używał skrótów, np. ,,wartość przechowywana przez zmienną’’, jednak należy pamiętać o tym, że zmienna jedynie wskazuje na obiekt, który tę wartość przechowuje.

Kolejność działań

Kolejność wykonywania działań jest taka jak przyjęta w matematyce, zatem najpierw potęgowanie, potem mnożenie i dzielenie a na końcu dodawanie i odejmowanie.

wynik = 10+10*2**3
print(wynik)
90

Jeśli chcemy zmienić kolejność wykonywania działań, stosujemy pary nawiasów ( ), przy czym możemy je zagnieżdżać, wtedy działania wykonują się zaczynając od najbardziej zagnieżdżonych wyrażeń. Warto czasem używać nawiasów nawet gdy nie zmieniają one kolejności wykonywanych działań, ale grupują wyrażenia w celu zwiększenia przejrzystości kodu:

wynik = ((10+10)*2) / (1+3) 
print(wynik)
10.0

Zauważ, że w wyrażeniu powyżej umieściłem spacje wokół znaku /, oznaczającym dzielenie, które jest tutaj ostatnim wykonywanym działaniem. Nie jest to konieczne dla prawidłowego działania kodu, ale zwiększa nieco jego przejrzystość.

Działanie z nawiasami można oczywiście umieścić bezpośrednio w poleceniu print():

print(((10+10)*2) / (1+3))
10.0

Typy danych

Dotychczas używaliśmy dwóch typów danych i co za tym idzie, zmiennych. Pierwsza zmienna przechowywała tekst, zwykle nazywany bardziej fachowo ciągiem tekstowym czy łańcuchem znaków (ang. string). Jest to po prostu zestaw znaków, który tak jest właśnie interpretowany przez program. Łańcuchami znaków zajmiemy się bliżej później, teraz przyjrzyjmy się bliżej liczbom. W powyższych przykładach używaliśmy liczb całkowitych, ale Python używa także liczb zmiennoprzecinkowych, przy czym zamiast przecinka używamy kropki.

Sprawdźmy jak wygląda praca z liczbami zmiennoprzecinkowymi i ich łączenie z liczbami całkowitymi:

1.2+1.0
2.2
1.2+1
2.2
1.0+1
2.0

Jak widać, jeśli choć jedna z liczb jest zmiennoprzecinkowa, wynik jest przedstawiany jako liczba zmiennoprzecinkowa. Dotyczy to także sytuacji, w której liczby całkowite przedstawiamy jako zmiennoprzecinkowe (np. 1.0).

W wielu językach programowania (np. Java, C) kiedy wprowadzamy w programie nową zmienną, musimy deklarować jej typ. W Pythonie typ wynika z przypisanych wartości (przypominam, że zmienna jedynie wskazuje na obiekt przechowujący wartość). Typ zmiennych, a właściwie wartości wskazywanych przez zmienne, możemy sprawdzić wykorzystując polecenie type():

a = 1
b = 1.0
c = a+b
d = a/a
e = "tekst"
print(type(a))
print(type(b))
print(type(c))
print(type(d))
print(type(e))
<class 'int'>
<class 'float'>
<class 'float'>
<class 'float'>
<class 'str'>

Typ int oznacza liczbę całkowitą (od ang. integer) , float zmiennoprzecinkową a str (string) łańcuch znaków. Zauważ, że wynik z dzielenia jest liczbą zmiennoprzecinkową, nawet gdy obie liczby użyte w działaniu są całkowite.

Możliwe jest przypisanie wartości wielu zmiennym w jednej linijce:

a, b, c, d = 1, 1.0, 5, "Ala"
print(a)
print(b)
print(c)
print(d)
1
1.0
5
Ala

Nie sprzyja to jednak przejrzystości kodu, zwłaszcza gdy zmienne przyjmują dane różnego typu.

Kolejnym typem jest typ boolowski (ang. boolean), zwany też typem logicznym. Może przybierać jedną z dwu wartości: True (prawda) lub False (fałsz). Wbrew temu, co się może wydawać na początku nauki programowania, jest on niezwykle przydatny i istotny. Bliżej zajmiemy się nim w dalszej części kursu, teraz poprzestaniemy na podstawowych informacjach.

prawda = True
print(prawda)
True
type(prawda)
bool

Funkcja bool() pozwala na przekształcenie wartości na typ boolowski. Zauważ, że 0 jest konwertowana na False, inne liczby na True. Ciąg znaków jest konwertowany na True.

print(bool(1))
print(bool(0))
print(bool(-17))
print(bool())
print(bool('DNA'))
print(bool(False))
print(bool('False'))
True
False
True
False
True
False
True

Zastanów się, dlaczego ostatnie polecenie zwróciło wartość True.

Przy okazji warto zauważyć, że w powyższym kodzie w parze nawiasów towarzyszących funkcji print() nie umieszczamy wartości, ani nazwy zmiennej. Zamiast tego, wpisujemy tam wywołanie innej funkcji (bool()). Funkcja bool() zwraca wartość, która jest bezpośrednio przekazywana funkcji print().

Konwersja danych

Powyżej wywołaliśmy polecenie bool(), które konwertowało podane wartości na typ boolowski. Możliwe są także konwersje do innych typów. Służą do tego polecenia: int() - do liczb całkowitych, float() - do liczb zmiennoprzecinkowych, str() do łańcucha znaków.

Zobaczmy jak to działa:

a = 1
print(type(a))
b = float(a)
print(b)
print(type(b))
c = bool(a)
print(c)
print(type(c))
d = str(a)
print(d)
print(type(d))
e = float("1")
print(e)
print(type(e))
f = "7"
print(f)
print(type(f))
g = int(f)
print(g)
print(type(g))
<class 'int'>
1.0
<class 'float'>
True
<class 'bool'>
1
<class 'str'>
1.0
<class 'float'>
7
<class 'str'>
7
<class 'int'>

Teraz sprawdź:

f = int("DNA")
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-11-83a0f7f10596> in <module>
----> 1 f = int("DNA")

ValueError: invalid literal for int() with base 10: 'DNA'

Jak widać nie udało się w tym przypadku teksty DNA liczbę, co nie powinno dziwić.

Niedokładne wartości

Przy okazji obliczeń, możesz natrafić na dziwny wynik:

1.0 - 1.1
-0.10000000000000009

Powinniśmy uzyskać -0.1 a otrzymaliśmy -0.10000000000000009. Jest to ,,przypadłość’’ wynikająca ze sposobu przechowywania liczb przez komputer i nie jest ograniczona bynajmniej do Pythona. Więcej na ten temat można przeczytać np. w dokumentacji Pythona: https://docs.python.org/3/tutorial/floatingpoint.html.

Zaokrąglanie liczb

Jednym ze sposobów radzenia sobie z podobnymi przypadkami jest zaokrąglanie liczb. Jest to również jeden ze sposobów wyświetlania liczb bez zbędnego rozwijania części dziesiętnej liczb zmiennoprzecinkowych. Można to zrobić przy pomocy funkcji round():

print(round(3.1415926535))
print(round(3.1415926535, 3))
liczba = 10/7
print(liczba)
zaokraglona = round(liczba)
print(zaokraglona)
zaokraglona_2 = round(liczba, 2)
print(zaokraglona_2)
3
3.142
1.4285714285714286
1
1.43

Jak widać na powyższych przykładach, funkcji round() można przekazać liczbę zmiennoprzecinkową (lub zmienną), wtedy liczba zostanie zaokrąglona do wartości całkowitej. Można też dodatkowo (po przecinku) przekazać liczbę wskazującą, do ilu miejsc po przecinku należy zaokrąglić przekazaną liczbę zmiennoprzecinkową.

Nazwy zmiennych

Wybierając odpowiednie nazwy dla zmiennych, należy stosować się do pewnych zasad. Niektóre z nich są obowiązkowe aby program w ogóle działał, inne należą do dobrych praktyk przyjających czytelności kodu.

Podstawowe zasady, których trzeba się trzymać to:

  • Nazwa zmiennej może się składać z: liter, cyfr, oraz znaków podkreślenia (_) zwanych też podkreślnikami.
  • Nazwa zmiennej nie może zawierać spacji (co wynika z powyższego, ale warto to podkreślić)
  • Nazwa zmiennej nie może zaczynać się od cyfry, czyli może zaczynać się od litery lub podkreślnika
  • Należy unikać słów, które są zarezerwowane w Pythonie do celów programistycznych (False, def, if, raise, None, del, import, return, True, elif, in, try, and, else, is, while, as, except, lambda, with, assert, finally, nonlocal, yield, break, for, not, class, from, or, continue, global, pass) a także nazw wbudowanych funkcji (np. print, type)
  • Python rozróżnia wielość liter, zatem np. nazwisko, Nazwisko i NAZWISKO to różne ciągi znaków i np. różne nazwy zmiennych.

Kolejne zasady pozwalają zachować m. in. czytelność kodu i trzymanie się konwencji nazewnictwa przyjętych w Pythonie:

  • Nazwy zmiennych powinny czytelnie określać przechowywane wartości. Nie ulegaj pokusie, zwłaszcza kiedy będziesz pisać długie i złożone programy, nadawania zmiennym krótkich nazw, które nic nie znaczą. Jeśli np. chcesz przechować nazwę gatunku, to niech zmienna nazywa się gatunek albo nazwa_gatunku a nie g czy ng. W chwili pisania programu będziesz wiedzieć o co chodzi, być może nawet zaoszczędzisz parę sekund na stukaniu w klawiaturę, ale kiedy wrócisz do kodu po paru dniach, tygodniach czy miesiącach, najprawdopodobniej stracisz dużo więcej czasu na dociekanie co oznaczają nazwy typu ng, czy z, zwłaszcza jeśli postanowisz także ,,zaoszczędzić czas’’ nie pisząc komentarzy do kodu (o czym później).
  • Nazwa zmiennej nie powinna być zbyt ogólna, ale z drugiej strony nie powinna być zbyt długa. Należy zachować równowagę między zbyt ogólnymi i zbyt długimi, choć precyzyjnymi nazwami.
  • Jeśli nazwa składa się z kilku słów, to w Pythonie przyjęło się używać do ich oddzielenia podkreślnika. Zatem zmienna, która przechowuje nazwę sekwencji białka powinna się nazywać np. nazwa_sekwencji_bialka a nie nazwasekwencjibialka (nieczytelne) czy nazwaSekwencjiBialka (czytelne, ale przyjęte raczej np. w języku Java, poza tym patrz poniżej).
  • Nazwy zmiennych nie powinny zawierać wielkich liter.
  • Unikaj używania liter spoza podstawowego zestawu przyjętego dla języka angielskiego, czyli m. in. ,,polskich liter’’ ą, ó, Ż itd. Zatem nazwij zmienną raczej roznica niż różnica. Można też po prostu używać anglojęzycznych nazw, zwłaszcza jeśli Twój kod mogą czytać osoby nie posługujące się językiem polskim.

Konwencje nazywania innych elementów języka, jak klasy, funkcje czy stałe omówimy później.

Interaktywny Python jako kalkulator

Otwórz terminal (pod Windows Anaconda Prompt) i wpisz polecenie:

python

W terminalu pokaże się krótka informacja a także na dole miejsce do wpisania poleceń oznaczona >>> (Wersja Pythona może być inna):

Python 3.7.4 (default, Aug 13 2019, 20:35:49) 
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Wpisz 2*2 i wciśnij Enter.

>>> 2*2
4
>>> 

Jak widać pojawił się wynik, a także możliwość wprowadzenia kolejnego polecenia. Użyj teraz klawisza . Pojawi się poprzednie polecenie:

>>> 2*2

Posługując się klawiszami strzałek ( oraz ) można poruszać się w historii poleceń i je odpowiednio zmodyfikować. Zmieńmy nasze poprzednie działanie:

>>> 2*2**3
16
>>> 

Teraz obliczmy przybliżone pole koła o promieniu 12 cm:

>>> r = 12
>>> pi = 3.14
>>> pi*r**2
452.16

Jeśli teraz chcemy policzyć pole dla koła o innym promieniu wpisujemy np:

>>> r = 24

Następne strzałką przywołujemy ponownie wzór i wciskamy Enter:

>>> pi*r**2
1808.64
>>> 

Nie musimy ponownie wpisywać wzoru, co oszczędza czas.

W ten sposób możemy pracować w spośób internaktywny z Pythonem, wpisując komendy i uzyskując bezpośrednio ich wynik. Taki tryb jest więc przydatny np. kiedy chcemy wykonać jakiś krótki kod, sprawdzić działanie polecenia albo szybko coś obliczyć. Podobny tryb pracy oferuje IPython (wywołanie poleceniem ipython). Jego możliwości są dużo większe i można o nich przeczytać np. w dokumentacji https://ipython.readthedocs.io/en/stable/ i na stronie projektu https://ipython.org/. Z tego projektu rozwinął się zresztą Jupyter.

Zadania

Zadanie 1

Napisz program, który obliczy stężenie molowe roztworu dla danych wartości: masy substancji rozpuszczonej, masy molowej substancji rozpuszczonej oraz objętości roztworu. Użyj zmiennych do przechowania wartości używanych w obliczeniu, oraz wyniku. Wydrukuj (na ekranie) dane wejściowe (z opisem) oraz wynik z dokładnością do jednego miejsca po przecinku.

Wzór na stężenie molowe to:

$$ c_{mol} = \frac{m_{s}}{M_{s} \cdot V_{r}} $$

gdzie: $$c_{mol}\ -\ stężenie\ molowe,\ m_{s}\ -\ masa\ substancji\ rozpuszczonej,$$ $$M_{s}\ -\ masa\ molowa\ substancji\ rozpuszczonej,\ V_{r}\ -\ objętość\ roztworu$$

Przykładowe rozwiązanie

masa_substacji_rozpuszczonej = 250
masa_molowa_substacji_rozpuszczonej = 120
objetosc_roztworu = 2

stez_molowe = masa_substacji_rozpuszczonej / (masa_molowa_substacji_rozpuszczonej*objetosc_roztworu)

print('masa substacji rozpuszczonej:')
print(masa_substacji_rozpuszczonej)
print('masa molowa substacji rozpuszczonej:')
print(masa_molowa_substacji_rozpuszczonej)
print('objętość roztworu:')
print(objetosc_roztworu)
print('Stężenie molowe:')
stez_molowe_zaokraglone = round(stez_molowe, 1)
print(stez_molowe_zaokraglone)

Wynik:

masa substacji rozpuszczonej:
250
masa molowa substacji rozpuszczonej:
120
objętość roztworu:
2
Stężenie molowe:
1.0

Zadanie 2

Wyobraź sobie, że 100 lat temu Twój prapradziadek złożył w Bardzo Solidnym Banku 100 dolarów na lokacie, która była i przez cały czas jest oprocentowana na 5% w skali roku, przy czym kapitalizacja następuje raz w roku.

Napisz program, który obliczy obecną kwotę na koncie i wyświetli go w zaokrągleniu do centa. Użyj zmiennych do przechowywania danych wejściowych i wyniku.

O sposobach obliczania procentu składanego, można przeczytać np. na Wikipedii.

Przykładowe rozwiązanie

kapital_poczatkowy = 100
stopa_procentowa = 0.05
lata = 100

kwota_na_koncie = kapital_poczatkowy*(1+stopa_procentowa)**lata
kwota_na_koncie = round(kwota_na_koncie, 2)
print("Końcowa kwota na koncie:")
print(kwota_na_koncie)

Wynik:

Końcowa kwota na koncie:
13150.13
Last updated on 14 Oct 2021
Published on 29 Sep 2020