Spis treści Skorowidz Poziom główny Poziom nadrzędny ©
«« Początek »» Koniec

Środowisko, czyli nasz plac zabaw

Bieżący rozdział poświęcony jest technicznym aspektom tworzenia i uruchamiania programów. Proponujemy naukę podstaw programowania w języku Python.

Rozpoczynamy od omówienia zestawu oprogramowania służącego temu celowi i od opisu jego instalacji. Następnie zaznajamiamy czytelnika z trybem interaktywnej współpracy z konsolą Pythona. W dalszej kolejności omówione są metody uruchamiania programów źródłowych oraz podstawowe konstrukcje języka.

Python jest językiem stosunkowo młodym; opracowany został w latach 90-tych XX wieku. Jego rosnąca popularność wynika z prostej składni, czytelnej notacji, swobody pozostawianej autorom kodu i bogatego zaplecza (batteries included).

[ Logo Pythona ]
Logo Pythona

Python jest językiem ogólnego przeznaczenia. Może służyć do przekształcania danych z pewnego formatu do innego, do prowadzenia obliczeń, do współpracy z systemami baz danych i z aplikacjami użytkowymi. Bywa stosowany do pisania graficznych konfiguratorów i instalatorów w systemach operacyjnych, do tworzenia graficznych interfejsów obsługi, do złożonych serwisów WWW, do symulacji komputerowej i wizualizacji zjawisk fizycznych oraz do wielu innych celów.

Nie ma znaczenia, z jakiego sprzętu i systemu operacyjnego korzystasz. Pythona możesz używać w systemach MacOS X, UNIX, Windows i kilku innych. Ten sam kod źródłowy, o ile został starannie napisany, bez wprowadzania zmian będzie się dało uruchomić w każdym spośród wymienionych systemów.

Dzięki liberalnej licencji użytkowania, z pracą w środowisku Python nie wiąże się konieczność zakupu dodatkowego oprogramowania. Istnieje komercyjne oprogramowanie przeznaczone do pisania i testowania kodu, ale nie jest ono niezbędne; także niektóre biblioteki użytkowe mogą wymagać zakupu licencji.

Instalacja

Całe niezbędne oprogramowanie można pobrać z wymienionych niżej węzłów dystrybucyjnych. Użytkownicy laboratoriów wydziałowych mogą pobrać większość niezbędnych pakietów instalacyjnych z naszego serwera http spod adresu http://mat.up.wroc.pl/software/byvendor/python.

Interpreter Pythona

Interpreter języka jest najważniejszym, i jedynym naprawdę niezbędnym do nauki w ramach tego kursu, pakietem oprogramowania.

Współczesna wersja języka i interpretera jest oznaczona numerem 3. Aktualizację opatrzoną numerem 3.12.0 wydano w październiku 2023 roku. Aktualizacja wersji linii 3.12 jest zagwarantowana do października 2028 (https://python.org/downloads). Aktualizowane są również wersje: 3.11 (do października 20276), 3.10 (do października 2026), 3.9 (do października 2025), oraz 3.8 (do października 2024).

Rozwój poprzedniej wesji języka został ostatecznie zakończony na wydaniu 2.7.18 w kwietniu 2020 roku. Różni się ona od wersji bieżącej w wielu istotnych szczegółach. Z przyczyn historycznych niniejszy tekst zawiera — co prawda już nieliczne — odwołania do wersji 2. Miejsca, w których różnice między wersjami języka są istotne, zostały oznaczone w tekście.

Istnieje kilka źródeł pakietów instalacyjnych:

python.org (http://www.python.org/ftp/python/)
kompletne środowisko na wolnej i otwartej licencji;
Anaconda (http://www.continuum.io)
środowisko uzupełnione o wiele pakietów do zadań naukowych i inżynieryjnych; obowiązuje nieco inna licencja;
ActivePython (http://www.activestate.com/Products/activepython/)
alternatywa w stosunku do poprzedniego; obowiązuje inna licencja; nowe wersje pojawiają się nieco później;
PyPy (http://www.pypy.org)
eksperymentalny interpreter (i kompilator JIT) Pythona napisany w Pythonie. PyPy nie obsługuje całej składni języka i wymaga specjalnych wersji bibliotek, ale programy uruchamiane pod jego kontrolą działają kilka razy szybciej niż pod „zwykłym” Pythonem.
dystrybucje systemów operacyjnych
użytkownicy wielu systemów operacyjnych (w tym większości dystrybucji Linuksa oraz systemów MacOS X) mają do dyspozycji pakiety instalacyjne Pythona przygotowane w ramach systemu;
pakiety oprogramowania użytkowego
wiele systemów użytkowych zawiera instalację Pythona jako wbudowanego języka skryptowego, poszerzającego możliwości zastosowań danego systemu. Są wśród nich pakiety grafiki użytkowej, systemy analizy danych, pakiety oprogramowania biurowego, pakiety obliczeń naukowo–inżynieryjnych. Niektóre z nich wskażemy w ostatnim rozdziale.

O różnych implementacjach interpreterów języka i o sposobach ich pozyskania traktuje rozdział Alternative Python Implementations dokumentacji firmowej.

Edytor programistyczny

Z uwagi na fakt, że kod źródłowy programów tworzonych przez użytkownika jest przechowywany w zwykłych plikach znakowych, nie ma potrzeby posiadania specjalnego edytora. Mimo to wygodnie jest korzystać z edytora wzbogaconego o wyspecjalizowane funkcje związane z konkretnym językiem programowania.

Poniżej krótki, i oczywiście niepełny, wybór takich edytorów.

Edytory ogólnego przeznaczenia ze wsparciem dla Pythona

Edytory z tej grupy są wyposażone w narzędzia pomocne przy tworzeniu kodu w języku Python, chociaż nie jest to ich główne przeznaczenie.

SciTE (http://www.scintilla.org/SciTE)
uniwersalny edytor kodu źródłowego i zbiorów danych; umożliwia łatwe uruchamianie kodu; rozpoznaje i podświetla składnię m.in. Pythona
Bluefish (http://bluefish.openoffice.nl/)
uniwersalny edytor umożliwiający łatwe uruchamianie kodu; rozpoznaje i podświetla składnię m.in. Pythona
Notepad++ (http://notepad-plus.sourceforge.net/)
uniwersalny edytor kodu źródłowego i zbiorów danych; rozpoznaje i podświetla składnię m.in. Pythona; instalacja tylko w systemach Windows
Vim (http://www.vim.org)
uniwersalny edytor o ogromnych możliwościach i osobliwym sposobie obsługi; rozpoznaje i podświetla składnię m.in. Pythona; da się zainstalować w każdym współczesnym systemie operacyjnym

Edytory dedykowane Pythonowi

Edytory z tej grupy są zaprojektowane specjalnie dla tworzenia kodu w języku Python.

IDLE
dostarczany w ramach typowej instalacji Pythona; godny polecenia, ale nieco trudniejszy w użytkowaniu od innych, np. od PythonWin
PythonWin
część PyWin32; godny polecenia; dostępny tylko dla systemów Windows
WingIDE (http://wingware.com/downloads/wingide-101)
wygodny edytor i debugger, okrojona część komercyjnego środowiska dla profesjonalistów
Komodo Edit (http://www.activestate.com/komodo_edit)
dobry edytor specjalistyczny, ale bez debuggera

Środowisko diagnostyczne

Edytor jest niezbędny przy tworzeniu kodu programu, a niekiedy także pozwala na jego uruchomienie. Środowisko diagnostyczne umożliwia przetestowanie działania napisanego kodu. Zazwyczaj, choć nie zawsze, jest ono wyposażone we własny edytor.

IDLE
składnik podstawowej dystrybucji Pythona
PythonWin
debugger zintegrowany z edytorem
WingIDE
debugger zintegrowany z edytorem; okrojona część komercyjnego środowiska dla profesjonalistów
WinPDb (http://www.digitalpeers.com/pythondebugger/)
dobry debugger, ale bez edytora
Komodo IDE
debugger zintegrowany z edytorem; wersja próbna komercyjnego środowiska

Dodatkowe biblioteki i moduły

NumPy (http://www.scipy.org/)
zaawansowane obliczenia numeryczne, niezbędne dla wielu innych bibliotek
Matplotlib (http://matplotlib.sourceforge.net/)
wizualizacja danych
Gnuplot-py (http://gnuplot-py.sourceforge.net/)
interfejs do programu graficznego Gnuplot
PilLow (https://pypi.python.org/pypi/Pillow/)
przetwarzanie obrazów rastrowych (wersja rozwojowa dawnego pakietu PIL)
EasyGUI (http://www.ferg.org/easygui, http://easygui.sourceforge.net)
łatwy w użyciu zestaw podstawowych okien dialogowych
PsycoPG (http://initd.org/pub/software/psycopg/)
dostęp do baz danych PostgreSQL
SciPy (http://www.scipy.org/)
tzw. obliczenia naukowe
SymPy (http://www.sympy.org/)
matematyczne obliczenia symboliczne
PyWin32 (http://starship.python.net/crew/mhammond/win32)
umożliwia komunikację z aplikacjami Windows korzystających ze standardowego interfejsu COM; tylko Windows
ComTypes (http://starship.python.net/crew/theller/comtypes/)
umożliwia komunikację z aplikacjami Windows używającymi własnych rozszerzeń interfejsu COM (np AutoCAD); tylko Windows
PyUNO (http://www.openoffice.org)
część instalacji OpenOffice; umożliwia dostęp do sesji OpenOffice i tworzenie makropoleceń dla tego środowiska
SDXF (http://pypi.python.org/pypi/SDXF, http://download.berlios.de/python/sdxf.py)
łatwy w użyciu generator rysunków w formacie dxf będący częścią pakietu graficznego Blender

Warunki i przebieg instalacji

Kolejność instalacji: interpreter, środowisko edycyjne, biblioteki.

Po pomyślnej instalacji pakietów zalecam:

  1. ustawienie w systemie ścieżek poszukiwań (PATH) pozwalających na uruchamianie programów python i pythonwin z wiersza poleceń (np. cmd lub bash). W systemach uniksowych jest to robione domyślnie; podobnie w przypadku instalacji Pythona 3 w systemach Windows;
  2. rozpakowanie pliku easygui.zip do podkartoteki Lib/site-packages lub site-packages w kartotece macierzystej Pythona;
  3. jednokrotnie wczytanie rozpakowanych bibliotek do interpretera Pythona przez użytkownika z prawami administracyjnymi w celu ich kompilacji; czynność ta zazwyczaj jest automatycznie wykonywana podczas instalacji;
  4. skonfigurowania środowiska graficznego tak, by pliki *.py były domyślnie „otwierane za pomocą” wybranych przez Ciebie edytorów (np. SciTE i PythonWin).

Interpreter Pythona

Rozpoczęcie pracy interpretera Pythona polega na uruchomieniu programu o nazwie (zależnie od systemu operacyjnego) python albo python3. Można w tym celu posłużyć się wierszem poleceń powłoki systemowej, np. uniksowej powłoki bash

[ja@komp sources]$ python3

albo windowsowej cmd

c:\Users\Ja\sources> python

choć jest też wiele innych sposobów. Po uruchomieniu powinniśmy w konsoli zobaczyć znak zgłoszenia interpretera Pythona

Zakończenie pracy interpretera wymusimy za pomocą funkcji systemowej Pythona

exit()

lub wpisując do konsoli Pythona znak sterujący oznaczający koniec danych; w systemach Windows jest to

<Ctrl>Z

zaś w systemach uniksowych

<Ctrl>D

Słowa kluczowe języka

Znaczenie słów kluczowych i reguły ich użycia są zdefiniowane na poziomie języka. Znaczenia tego nie wolno zmieniać, co oznacza m.in., że słowa kluczowe nie mogą być nazwami zmiennych, modułów, argumentów podprogramów ani żadnych innych obiektów w kodzie źródłowym.

Dokumentacja różnych wersji Pythona wymienia następujące słowa kluczowe:

False None True and as assert async await break class continue def del elif else except exec finally for from global if import in is lambda nonlocal not or pass print raise return try while with yield

Podstawowe znaczenie słów oznaczonych symbolem jest objaśnione w toku niniejszego kursu. Słowa oznaczone symbolem nie są objaśnione ani używane podczas kursu.

W Pythonie 3 zestaw słów kluczowych kilkakrotnie podlegał modyfikacji. Nowe słowa wyróżniono w powyższym spisie kolorem zielonym; słowa usunięte oznaczono kolorem szarym. Pozostałe słowa należą do wersji 2 i 3 języka.

Komentarze

Przypomnijmy, że komentarze nie wpływają na tok czynności opisany w programie. Ich rola polega na dokumentowaniu sposobu działania programu.

W Pythonie istnieją dwa rodzaje komentarzy:

W poszukiwaniu informacji…

Przy poszukiwaniu informacji na temat elementów języka i dostępnych struktur danych przydatne są funkcje help() i dir():

help()
help(obiekt)

Funkcja help() udostępnia systemowy opis wskazanego obiektu. W przypadku, kiedy nazwa obiektu nie została podana, opis dotyczyć będzie sesji Pythona.

dir(obiekt)
dir()

Funkcja dir() udostępnia spis zawartości wskazanego obiektu. W przypadku, kiedy nazwa obiektu nie została podana, dostaniemy spis obiektów dostępnych w bieżącej sesji Pythona.

Python jako prosty kalkulator

Najprostszym sposobem użycia interpretera jest wykorzystanie go w roli kalkulatora obliczającego na bieżąco wartości wyrażeń różnych typów.

Spacje między wartościami i symbolami działań nie są istotne. Zakończenie wiersza (Enter) wymusza jego interpretację.

Przykłady

1+2+3
6
3/4
0
3.0/4
0.75
float(3)/4
0.75
float(3/4)
0.0
2**(1/2)
1
2**0.5
1.4142135623730951
2**3.0
8.0
'1' + '2' + '3'
'123'
'A' + 'l' + 'a'
'Ala'

Jak widać, wyniki obliczane przez ten kalkulator nie zawsze są tym, czego się spodziewamy. Żeby zrozumieć zasady obliczania, musimy powrócić do pojęcia typu danych, i zrozumieć, w jaki sposób typy danych są zrealizowane w Pythonie.

Typy danych w Pythonie

W tym rozdziale usystematyzujemy wiedzę na temat podstawowych typów danych dostępnych w Pythonie. Niezbędna jest znajomość charakterystyk typów danych, przynajmniej w zakresie opisanym w rozdziale 2. oraz elementarne doświadczenie w pracy z konsolą Pythona (choćby po to, by umieć rozpocząć i zakończyć sesję).

Jak już stwierdzono wcześniej, istotą typu danych jest:

  1. określenie zbioru dozwolonych wartości i ich znaczenia,
  2. określenie zestawu dozwolonych operacji.

W Pythonie każda wartość należy do pewnego typu danych.

Typ można sprawdzić za pomocą instrukcji type(obiekt), na przykład:

type(1)
<type 'int'>
type(1.0)
<type 'float'>
type('1')
<type 'str'>
type(True)
<type 'bool'>
type(None)
<type 'NoneType'>

Niżej charakteryzujemy najważniejsze standardowe (tzn. wbudowane w język) proste (tzn. takie, że należące do nich wartości nie posiadają rozbudowanej struktury wewnętrznej) typy danych dostępne w Pythonie.

Liczby całkowite

Python w weersji 3 oferuje typ danych całkowitoliczbowych bez wskazania ograniczenia zakresu wartości. Ograniczeniem wartości typu long jest jedynie ilość dostępnej pamięci operacyjnej w systemie.

Działania

a + b	# dodawanie liczb
a - b	# odejmowanie liczb
a * b	# mnożenie liczb
a / b	# dzielenie liczb całkowitych daje wynik zmiennopozycyjny
a // b	# dzielenie całkowite
a % b 	# reszta z dzielenia a przez b
a ** b	# potęgowanie liczb

W Pythonie 3 operator dzielenia / daje wynik będący liczbą zmiennopozycyjną. Warto więc używać operatora // za każdym razem, kiedy zależy nam na wyniku całkowitoliczbowym.

Odstępy między symbolem działania a jego argumentami nie mają znaczenia; zostały wstawione dla zwiększenia czytelności.

Kolejność operacji jest określona przez twórców konkretnego języka lub środowiska. W Pythonie jest ona zgodna z tradycyjną notacją matematyczną, przyznającą priorytety poszczególnym działaniom arytmetycznym. Operacje dodawania i odejmowania mają priorytet niższy, niż operacje mnożenia i dzielenia, te zaś z kolei ustępują priorytetem operacji potęgowania. Przy tym samym priorytecie, działania wykonywane są w kolejności czytania tekstu „od lewej do prawej”.

Chcąc wymusić inną kolejność działań, należy użyć nawiasów okrągłych. Nawiasy takie wolno zagnieżdżać.

Jeżeli zapis liczby całkowitej rozpoczyna się cyfrą 0, to interpreter Pythona w wersji 2.x języka przyjmował, że liczbę tę podano w systemie ósemkowym. Przy takim zapisie wolno używać jedynie cyfr od 0 do 7.

12
12      # tj. 1*10 + 2*1 
012
10      # tj. 1*8 + 2*1 
29
29
029
  File "<stdin>", line 1
    029
      ^
SyntaxError: invalid token      # w systemie ósemkowym nie ma cyfry 9

Jeżeli zapis liczby całkowitej rozpoczyna się od znaków 0x, to interpreter Pythona przyjmuje, że liczbę tę podano w systemie szesnastkowym. Cyfry szesnastkowe przypisane liczbom naturalnym od 0 do 15 oznaczane są symbolami: 0123456789abcdef, przy czym dopuszczalne jest także użycie wielkich liter.

12
12
0x12
18       # tj. 1*16 + 2*1 
0x1b3
435      # tj. 1*256 + 11*16 + 3*1; cyfrze b odpowiada wartość liczbowa 11

Jeżeli zapis liczby całkowitej rozpoczyna się od znaków 0b, to interpreter Pythona przyjmuje, że liczbę tę podano w systemie dwójkowym. W tym przypadku dozwolone jest użycie jedynie cyfr: 0 i 1.

11
12
0b11
3       # tj. 1*2 + 1*1
0b1011
11      # tj. 1*8 + 0*4 + 1*2 + 1*1

Twórcy Pythona 3 uznali, że niejednolitość opisanych wyżej reguł określania stałych liczbowych jest wadą języka. Na dodatek, konwencja nakazująca traktowanie zapisów rozpoczynających się zerem jako liczb w notacji ósemkowej jest nieintuicyjna. Dlatego w Pythonie 3 konwencja ta została zmieniona. Dla systemu ósemkowego wprowadzono notację 0o, analogiczną do notacji 0b i 0x. Przy tym, dla uniknięcia nieporozumień co do użytej podstawy liczbowej, stałe całkowitoliczbowe różne od zera nie nie mogą być określane ciągami cyfr dziesiętnych rozpoczynającymi się cyfrą 0. Użycie takic hstałych generuje błąd składniowy. (Na przykład ciąg znaków 012, który w Pythonie 2 oznaczał liczbę 10, w Pythonie 3 jest niedozwolony jako stała liczbowa. Legalne są natomiast zarówno 0o012, jak 0o12.)

Reguły te dotyczą wyłącznie stałych (literałów) umieszczanych w kodzie źródłowym. Podczas czytania liczb z urządzeń znakowych (terminali, plików itp.) dane tekstowe muszą być poddane konwersji na typy liczbowe; w tym przypadku dopuszczalne są jedynie ciągi cyfr (choć niekoniecznie dziesiętnych) niepoprzedzone sekwencją 0znak wskazującą użytą podstawę systemu pozycyjnego. Mogą one rozpoczynać się dowolną liczbą zer.

Trzy działania

a ^ b
a | b
a & b

określone dla liczb całkowitych oznaczają odpowiednio alternatywę wykluczającą (xor), alternatywę (or) oraz koniunkcję (and) cyfr dwójkowych na odpowiadających sobie pozycjach.

Przykłady

type(1)
type(1L)
1+2+3
1+2L+3
2147483647+1
1+2*3+4
(1+2)*(3+4)
6+(5*(4+3))**2
2**3
10**2
10**20
long(1)
int(10**20)
1/2
10 / 3
10 % 3
2**3**4
2**(3**4)
(2**3)**4
123
0123
0x10**2
0xff + 1
0xab + 012 - 3

Liczby zmiennopozycyjne

W Pythonie do reprezentowania liczb rzeczywistych służy typ zmiennopozycyjny o nazwie float.

liczby rzeczywiste (typ float)
1.0, 1.5, -2.122, 123.44, 1.33E-5, -5.4333E+4

Część dziesiętna jest oddzielona od części całkowitej za pomocą znaku kropki.

W zapisie pojedynczej danej liczbowej mogą wystąpić jedynie: opcjonalnie znak + lub - na początku, liczba dziesiętna opisana ciągiem cyfr zawierającym co najwyżej jedną kropkę, po czym opcjonalnie litera E (lub e) z następującym po niej ciągiem cyfr, opcjonalnie poprzedzonym znakiem + lub -.

Dane typu floatdanymi zmiennopozycyjnymi podwójnej precyzji wg terminologii IEEE.

Działania

a + b	# dodawanie liczb
a - b	# odejmowanie liczb
a * b	# mnożenie liczb
a / b	# dzielenie liczb rzeczywistych daje wynik rzeczywisty
a // b	# dzielenie całkowite, z odrzuceniem części ułamkowej
a % b 	# reszta z dzielenia a przez b
a ** b	# potęgowanie liczb

Priorytety operacji są w przypadku danych zmiennopozycyjnych takie same, jak w przypadku danych całkowitoliczbowych. Takie same są też reguły grupowania wyrażeń za pomocą nawiasów.

Przykłady

type(1.0)
float(1)
1.0/2.0
8.0//3.0
2.0**3+1
(2.0**3)+1
2.0**(3+1)
2**(1/2)
2**(1/2.0)
2**0.5
(1-2**0.5) / (1+2**0.5)
1+2+3.0
10.0 / 3
10.0 // 3
10.0 % 3

Z modelu zmiennopozycyjnego wynika, że nie zawsze wynik obliczeń jest dokładny. Nie zawsze dana typu rzeczywistego jest tą liczbą, za którą ją zwykliśmy uważać:

1.0/2
0.5
1.0/10
0.10000000000000001
1.0/10 == 0.1
True
0.1
0.10000000000000001
0.10000000000000001 == 0.1
True

Przyczyny takiego zachowania zostały wyjaśnione w rozdziale 2.2. Pozornie paradoksalny wynik jest konsekwencją faktu, że liczba 0.1 nie ma dokładnej reprezentacji zmiennopozycyjnej w arytmetyce dwójkowej. Interpreter Pythona nie ukrywa tego faktu przed użytkownikiem, podczas gdy systemy użytkowe używają różnych metod, nieraz wyrafinowanych, dla przedstawienia danych w postaci zgodnej z potocznymi oczekiwaniami.

Wartość zmiennopozycyjna NaN (patrz podrozdział 2.2.2.) jest reprezentowana w Pythonie jako nan. Nie jest to nazwa, tylko wartość. Z uwagi na fakt, że NaN jest potrzebna tylko w sytuacjach wyjątkowych, nie ma możliwości jej użycia w wyrażeniach jako stałej. Najprostszym sposobem wygenerowania danej o wartości nan jest konwersja float('NaN'); wartość tę da się oczywiście przypisać zmiennej:

a = float('NaN')

Wszelkie obliczenia numeryczne wykorzystujące wartość nan prowadzą do wyników o wartości nan.

Na dodatek wszelkie przyrównania i porównania danych liczbowych z nan, oraz wartości nan z samą sobą, dają zawsze wynik negatywny:

n = float('NaN')
n == 1.0
False
n == n
False
n <= 1.0
False
n >= 1.0
False
n != 1.0
True
n != n
True

Teksty

Dane tekstowe (typ str) są ciągami znaków. Wartości tekstów podajemy w ogranicznikach: w pojedynczych apostrofach lub w cudzysłowach technicznych.

Napisy objęte ogranicznikami "…" lub '…' muszą mieścić się w jednym wierszu kodu źródłowego.

'xxx'
'xxx'
"xxx"
'xxx'
type('Ala')
<type 'str'>
type('123')
<type 'str'>

Napisy objęte ogranicznikami """…""" lub '''…''' mogą rozciągać się na kilka wierszy kodu źródłowego.

"""napis 
wielowierszowy"""

Działania

a + b	# łączenie napisów a i b
a * b	# zwielokrotnianie napisów; a jest napisem, b jest liczbą całkowitą nieujemną lub na odwrót

Znaki w napisach są numerowane. Pierwszy znak ma zawsze numer 0.

Pobieranie fragmentów napisów

napis[0]	# pierwszy w kolejności element (znak) napisu
napis[1]	# drugi, itd.
napis[-1]	# ostatni
napis[-2]	# przedostatni, itd.
napis[0:3]	# fragment napisu obejmujący znaki od pierwszego do trzeciego
napis[2:]	# od trzeciego aż do końca
napis[-2:]	# dwa ostatnie znaki

Długość ciągu znaków obliczamy za pomocą funkcji len()

len(napis)

Operacją blisko związaną z pobieraniem fragmentu tekstu jest sprawdzanie, czy dany znak lub tekst jest fragmentem innego tekstu. W Pythonie da się to sprawdzić korzystając z operatora przynależności in:

'a' in 'Ala ma asa'
True
'z' in 'Ala ma asa'
False

Można w ten sposób badać nie tylko pojedyncze znaki, ale dowolne teksty:

'Ala' in 'Ala ma asa'
True
'As' in 'Ala ma asa'
False

Tym sposobem nie dowiemy się, ile razy ani na której pozycji dany tekst występuje w dłuższym tekście.

Operator in odnosi się zawsze do przynależności, choć niekoniecznie do danych typu tekstowego.

Istnieje także operator not in. Za jego pomocą sprawdza się, czy dany element nie należy do danego zbioru.

in oraz not słowami kluczowymi Pythona.

Znak odwrotnego ukośnika jest wewnątrz napisów znakiem sterującym. Od niego rozpoczynają się nazwy ważnych znaków specjalnych, m.in.:

'\n'	# znak nowego wiersza (LF)
'\t'	# znak tabulacji
# Ooo! jak w wyrażeniach regularnych!
'\r'	# znak powrotu do początku wiersza (CR)
# Sekwencja '\r\n' (CR+LF) jest używana na końcach wierszy w plikach tekstowych w systemach Windows
'\\'	# znak ukośnika \

Znak sterujący przydaje się także w sytuacji, kiedy wewnątrz napisu ograniczonego cudzysłowami chcemy umieścić taki sam symbol cudzysłowu:

"'"
'\''	# znak apostrofu '
'"'
"\""	# znak cudzysłowu "

Kolejne zastosowanie symbolu sterującego wiąże się z kodami znaków UNICODE. Będzie o tym mowa w podrozdziale 6.1. Do tego czasu założymy, że zamierzamy używać w napisach wyłącznie podstawowych znaków ASCII, tj. cyfr arabskich, liter łacińskich i znaków przestankowych.

Przykłady

'Ala' + ' ' + 'ma' + ' '+ 'kot' + 'a.'
'Ala ma kota.'
2*'Ala' + ' ma ' + 2*('kot'+'a') + '.'
'AlaAla ma kotakota.'
'Komputerowe wspomaganie projektowania'[0]
'K'
'Komputerowe wspomaganie projektowania'[0:10]
'Komputerow'
'Komputerowe wspomaganie projektowania'[-1]
'a'
'Komputerowe wspomaganie projektowania'[-8:]
'ktowania'
"""Komputerowe
wspomaganie
projektowania"""
'Komputerowe\nwspomaganie\nprojektowania'
"Komputerowe\nwspomaganie\nprojektowania"
'Komputerowe\nwspomaganie\nprojektowania'
len('Ala i As')
8
len('Ala\ti\tAs')
8
len('Ala\ti\tAs\n')
9
'przedmiot \'Komputerowe wspomaganie projektowania\''
"przedmiot 'Komputerowe wspomaganie projektowania'"

Dla informacji, że instrukcja lub wyrażenie nie zostało zakończone, zgłoszenie interpretera przybiera postać ... zamiast >>>.

Teksty a formatowanie danych

Operacja formatowania napisów bywa użyteczna przy generowaniu raportów wynikowych. Służy do niej operator %:

szablon % arg	# podstawianie sformatowanych wartości umieszczonych w arg do wzorca szablon

Wynik formatowania jest zawsze daną typu tekstowego.

Napis wzorcowy szablon może zawierać dowolny tekst. Miejsca podstawienia argumentów oznacza się w nim za pomocą kodów: %s dla argumentu tekstowego, %d dla argumentu będącego liczbą całkowitą, %f dla argumentu będącego liczbą zmiennopozycyjną. Kody argumentów można uzupełniać dyrektywami o sposobie ich przedstawienia, tj. liczbie znaków i dokładności liczb. Dyrektywa %% oznacza znak procenta.

Wartość arg może być albo pojedynczym argumentem typu logicznego, tekstowego lub liczbowego, albo uporządkowanym ciągiem takich argumentów. W przypadku, kiedy typ dostarczonego argumentu jest inny, niż opisany przez dyrektywę formatowania, dokonywana jest konwersja.

W przypadku formatowania pojedynczej danej tekstowej operatora % można użyć następująco (napis zostanie po prostu wstawiony w miejsce symbolu %s):

'miasto %s'
'miasto %s'
'miasto %s' % 'Warszawa'
'miasto Warszawa'
'miasto %s' % 'Kraków'
'miasto Kraków'

W przykładzie niżej napisy zostaną przedstawione przy użyciu co najmniej 20 znaków.

'miasto %20s'
'miasto %20s'
'miasto %20s' % 'Warszawa'
'miasto              Warszawa'
'miasto %20s' % 'Wrocław'
'miasto               Wrocław'
'miasto %20s' % 'Zielona Góra'
'miasto          Zielona Góra'

W przypadku formatowania pojedynczej danej liczbowej operatora % używa się następująco:

'%f' % 123.45'	# przedstawienie domyślne
'123.450000'
'%.3f' % 123.45'	# 3 cyfry dziesiętne
'123.450'
'%10.4f' % 123.45'	# co najmniej 10 znaków, w tym 4 cyfry dziesiętne
'  123.4500'
'%20.12f' % 123.45'	# co najmniej 20 znaków, w tym 12 cyfr dziesiętnych
'    123.450000000000'

Dalsze szczegóły dotyczące operacji formatowania, zwłaszcza dotyczące przypadku większej liczby argumentów, podamy w podrozdziale 6.6, po wprowadzeniu typów danych umożliwiających przechowywanie ciągów wartości.

Dane logiczne

Do zarządzania wartościami logicznymi służy w Pythonie typ bool zawierający dwie wartości:

True
wartość logiczna reprezentująca prawdę
False
wartość logiczna reprezentująca fałsz
type(True)
type(False)

Nazwy stałych logicznych True i False są w Pythonie 3 słowami kluczowymi.

Działania na wartościach typu logicznego

and, or, not — operatory logiczne obliczające koniunkcję, alternatywę i negację wartości dostarczonych wyrażeń.

True or False
not True

and, or, not słowami kluczowymi Pythona.

Operatory o wynikach typu logicznego

Skąd się biorą dane logiczne? często z przyrównań innych danych

a == b	# sprawdzenie, czy dwie wartości są równe
a != b	# sprawdzenie, czy dwie wartości są różne
a <> b	# sprawdzenie, czy dwie wartości są różne

W starszych wersjach Pythona notacje a != b i a <> b można stosować zamiennie. W Pythonie 3 operator <> został usunięty z języka.

albo z ich porównań

a > b
a < b
a >= b
a <= b

W Pythonie typy porównywanych wartości nie muszą być zgodne, ale jeżeli się różnią, to trzeba umieć zinterpretować wynik.

1+1 == 2	# przyrównanie wyrażeń liczbowych
True
10 == 10.0	# przyrównanie liczb różnych typów; automatyczna konwersja
True
10 == '10'	# przyrównanie liczby i tekstu; zawsze False
False
10 > 2	# porównanie liczb
True
10 > 2.0	# porównanie liczb różnych typów
True
'10' > '2'	# porównanie napisów, obowiązuje porządek słownikowy
False
'10' > 2	# porównanie danych różnych typów -- co to znaczy? 
True
'20' > 20	# na pewno co innego, niż byśmy chcieli... tylko co?
True
'20' > 10
True
'10' > 20
True
10 > '20'
False
20 > '10'
False

W Pythonie 2 wynik porównania danych mających niezgodne typy zależy od porównania nazw tych typów. Zatem nigdy nie jest to wartość sensowna z punktu widzenia „zwykłego użytkownika”.

W Pythonie 3 próby porównywania danych mających niezgodne typy prowadzą do wygenerowania błędu.

W jaki sposób przyrównywać bądź porównywać wiele wartości naraz? Czy to się w ogóle da zrobić?

Na przykład zdanie testujące przynależność wartości x do przedziału [a, b) w klasycznym rachunku zdań ma postać (ax) ∧ (x < b). W notacji matematycznej bywa ono wyrażane krócej jako (ax < b). Powstaje pytanie: czy notacja ta jest dopuszczalna w językach programowania?

W Pythonie — tak. Oba zapisy

(a <= x) and (x < b)
a <= x < b

wyrażają w zasadzie ten sam warunek (istnieją sytuacje, w których ostateczne efekty spowodowane użyciem tych wyrażeń są odmienne, jednak nie dotyczy to przypadków, kiedy a, b i x są stałymi, zmiennymi, ani wynikami działań arytmetycznych na stałych i zmiennych).

W innych językach — niekoniecznie, ale na ogół nie. Nieprzemyślane użycie skrótowej notacji bywa powodem błędów rzeczowych.

W językach, w których operatory przyrównań i porównań są konsekwentnie traktowane jak operatory dwuargumentowe, przyjęta zostanie następująca interpretacja:

(ax < b) (a) ≤ (x < b)

Nie ma ona nic wspólnego z pierwotnym sensem warunku. Jednak jeżeli środowisko wykonawcze dokonuje konwersji wartości logicznych na dane liczbowe (a jest to norma w wielu językach programowania), to odpowiedź — mimo że bezsensowna z punktu widzenia użytkownika — zostanie udzielona.

Analogiczna składnia jest dozwolona także w przypadku innych operatorów. Na przykład wyrażenia

a == b == c
a != b != c
a != b <= c
a < c != b < d

są równoważne odpowiednio wyrażeniom

(a == b) and (b == c)
(a != b) and (b != c)
(a != b) and (b <= c)
(a < c) and (c != b) and (b < d)

czyli koniunkcji zdań powstałych przez rozdzielenie operatorów.

Chcąc skłonić Pythona do innej kolejności interpretacji, powinniśmy użyć nawiasów, np. a == (b == c), (a < c) != (b < d), itp.

Szczególnym sposobem przyrównywania jest sprawdzenie, czy dwa obiekty są tożsame, czyli identyczne. Służy do tego operator is oraz blisko z nim związany is not.

a == b	# sprawdzenie, czy dwie wartości są równe
a is b	# sprawdzenie, czy wartości a i b są reprezentowane przez ten sam obiekt
a is not b	# sprawdzenie, czy wartości a i b  są reprezentowane przez dwa różne obiekty

Tożsamość oznacza znacznie więcej, niż równość; szczegóły objaśnimy w podrozdziale 10.1.3.

Operatory is i is not odnoszą się do sposobu przechowywania danych w pamięci.

is oraz not słowami kluczowymi Pythona.

Operatorami zwracającymi wartości logiczne są także operatory przynależności: in i blisko z nim związany not in. Była o nich mowa w podrozdziale 5.3.3. przy okazji omawiania danych tekstowych; powrócimy do nich jeszcze raz w podrozdziałach rozdziału 6. poświęconych listom, słownikom i zbiorom.

a in b		# sprawdzenie, czy wartość a jest elementem b
a not in b	# sprawdzenie, czy wartość a nie jest elementem b

Wartości wyrażeń a not in b (a nie jest elementem b) oraz not a in b (nieprawda, że a jest elementem b) są jednakowe.

Liczby zespolone

Python ma wbudowany typ liczb zespolonych (typ complex). W notacji zespolonej część urojoną oznacza się za pomocą wartości liczbowej z przyrostkiem j. Współczynnika liczbowego nie wolno pominąć.

Do wykonywania działań arytmetycznych na danych zespolonych służą operatory + - * / ** znane z działań na liczbach zmiennopozycyjnych.

1j
1j
1j**2
(-1+0j)
(1j - 2.5)*2.0 - 0.5j
(-5.0+1.5j)

Dana zespolona o zerowej części urojonej nie jest daną rzeczywistą.

type(-1+0j)
<type 'complex'>
(-1+0j) == -1.0
True

Do wyłuskania części rzeczywistej i części urojonej służą odpowiednio operatory real i imag (notacja obiektowa):

(-1+2j).real
-1.0
(-1+2j).imag
2.0

Zwracają one wartości typu zmiennopozycyjnego float, nawet jeśli ich części ułamkowe są równe zeru.

Inne typy liczbowe

W Pythonie możliwe jest również wykonywanie obliczeń na liczbach dziesiętnych (Decimal) oraz na liczbach wymiernych (Fraction) z utrzymaniem pełnej dokładności wyników. Niniejsze opracowanie nie omawia odpowiednich typów danych ani sposobu ich użycia.

Data i czas

Do obsługi danych dotyczących dat, terminów i odstępów czasu służy w Pythonie moduł datetime. Umożliwia on większość typowych operacji na datach. Wartości dat są przechowywane jako dane typu złożonego.

import datetime
datetime.date.today()	# bieżąca data
datetime.date(2011, 2, 22)
str(datetime.date.today())	# jako napis
'2011-02-22'
datetime.date(2011,01,01)	# wskazana data
datetime.date(2011, 1, 1)
datetime.date.today() - datetime.date(2011,01,01)	# czas między dwiema datami
datetime.timedelta(52)
datetime.date.today().year	# rok z danej daty
2011
datetime.date.today().month	# miesiąc z danej daty
2
datetime.date.today().day	# dzień miesiąca z danej daty
22
datetime.date.today().weekday()	# dzień tygodnia z danej daty
1
datetime.date(2010, 12,30) + datetime.timedelta(10)	# data plus czas trwania w dniach
datetime.date(2011, 1, 9)

Dokładność reprezentacji dat jest ograniczona do dni kalendarzowych. Bardziej precyzyjne obliczenia dotyczące czasu przeprowadza się w podobny sposób za pomocą struktur udostępnianych przez moduł datetime, m.in. datetime.time (czas zegarowy w obrębie doby), datetime.timedelta (czas trwania, czyli przedziały czasu) oraz datetime.datetime (data + czas zegarowy).

Wartość None

None — nic. Bardzo ważna wartość używana do wyrażania braku sensownej wartości, nieistnienia danej, itp.

W Pythonie 3 słowo None jest słowem kluczowym.

None
bool(None)
str(None)
int(None)

Łatwo sprawdzić, że wartość None należy do typu danych o nazwie NoneType:

type(None)
<type 'NoneType'>

Do przedstawiania brakujących danych liczbowych lepiej od None nadaje się wartość nan. W przeciwieństwie do None, nan jest wartością typu zmiennopozycyjnego, więc jej użycie w rachunkach nie powoduje błędu i zawsze zwraca wynik nan. Najprostszym sposobem uzyskania wartości nan jest wyrażenie float('NaN').

Typy jako wartości

Ciekawostką jest, że same typy danych są wartościami typu type.

type(int)
<type 'type'>
type(float)
<type 'type'>
type(type)
<type 'type'>
type(1.0) == int
False
type(1.0) == float
True

Sprawdzenie niektórych typów prowadzi do trudności. Na przykład

type(None)
<type 'NoneType'>
type(NoneType)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'NoneType' is not defined

Błąd wynika z faktu, że typ NoneType i jego właściwości domyślnie nie są udostępniane użytkownikowi za pomocą nazwanego obiektu. Mimo to możemy sprawdzić:

type(type(None))
<type 'type'>

Konwersje typów

Konwersja jest to zamiana wartości pewnego typu na odpowiadającą jej wartość innego typu. W Pythonie konwersję wymusza nazwa typu z wartością umieszczoną w nawiasie jako argument. Nie każda konwersja jest wykonalna.

str(1.0)	
str(True)
float(1)
int(2.5)
float('1.23')
int('2.5')
bool(1)
bool(2)
bool('1')
bool('a')
...

Przy konwersji do typu logicznego, wartości liczbowe 0 i 0.0, wartość tekstowa "" (pusty napis), wartość None, a także, co się okaże istotne w przyszłości, puste listy [ ] i ( ), są zamieniane na wartość logiczną False. Wartościom liczbowym różnym od zera, niepustym napisom i niepustym listom konwersja taka przypisuje wartość logiczną True. Właściwości te są bardzo często pomocne podczas konstruowania i sprawdzania warunków.

bool(0)	
False
bool(1)
True
bool(2)
True
bool("")
False
bool("Ala")
True
bool("As")
True

Wynika stąd, że konwersja, jako operacja nieodwracalna, może prowadzić do utraty informacji. Oto przykłady:

bool(1)
True
bool(2)
True
True == 1
True
True == 2
False

Kiedy konwersja może wprawić nas w zakłopotanie? Wtedy, kiedy jej nie rozumiemy do końca. Na przykład:

str(True)
'True'
True == 'True'			# typy bool i str nie są zgodne, wynik zawsze False
False
True == 1				# niejawnie dokonuje się konwersja typu bool na int
True
int(True)				# eksperyment potwierdzający powyższe przypuszczenie
1
str(True) == str(1)			# obie strony przyrównania są tego samego typu str, przyrównujemy napisy 'True' i '1'
False
bool('True') == bool('False')	# każdy niepusty napis jest konwertowany na True
True

Python jako silny kalkulator

Umiemy już używać sesji Pythona do doraźnego obliczania wartości wyrażeń. Rozumiemy też, od czego zależy typ otrzymywanego wyniku. Czas poszerzyć możliwości naszego kalkulatora.

Używanie zmiennych, czyli kalkulator z pamięcią…

…a raczej z dowolną ilością pamięci.

Do obszarów pamięci przechowujących wartości będziemy się odwoływać za pomocą zmiennych. Zmienne są rozpoznawane za pomocą nazw, nadawanych im przez użytkownika.

Wygodnie jest myśleć o zmiennych jak o pojemnikach umożliwiających przechowywanie wartości. W przyszłości okaże się, że analogia ta nie jest zupełnie ścisła, i że w Pythonie zmienne są raczej „etykietami” takich pojemników.

Tworzenie zmiennych

Nową zmienną inicjujemy, zapamiętując pewną wartość pod nowo nadaną nazwą:

nazwa = wartość # przypisuje wartość zmiennej o podanej nazwie

Nazwa winna być słowem składającym się wyłącznie z liter łacińskich, cyfr i znaku podkreślenia, przy czym nie może rozpoczynać się cyfrą. Nazwa nie może też być słowem kluczowym języka. Wynika z tego, że nazwa nie może zawierać spacji (podobne reguły rządzą nazwami obiektów w wielu innych środowiskach i warto ich przestrzegać, nawet jeśli w danej sytuacji nie są koniecznością). Wielkie i małe litery są w nazwach rozróżniane.

Poniższe nazwy nie są równoważne:

dlugoscwektora
dlugosc_wektora
dlugoscWektora
DlugoscWektora

choć wszystkie są równie sensownymi kandydat(k)ami na nazwę pewnego obiektu.

Poniższe nazwy są nielegalne (czyli de facto nie mogą być nazwami):

długość wektora	# bo zawiera spacje i litery spoza alfabetu łacińskiego
długośćWektora	# bo zawiera litery spoza alfabetu łacińskiego	
dlugosc wektora	# bo zawiera spacje
2dlugoscwektora	# bo rozpoczyna się od cyfry
while	# bo jest słowem kluczowym

Próba użycia niezadeklarowanej nazwy w obliczanym wyrażeniu jest nielegalna i prowadzi do błędu.

wartosc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'wartosc' is not defined
wartosc = 123.45
wartosc
123.45
wartosc = wartocs + 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'wartocs' is not defined

Jeżeli zmienna o wskazanej nazwie już istnieje, to podczas przypisania zostanie jej nadana nowa wartość.

ktos = 'Ala'
cos = 'kot'
ktos + ' ma ' + cos+'a.'
'Ala ma kota.'
zdanie = ktos + ' ma ' + cos+'a.'
zdanie
'Ala ma kota.'
ktos = 'Zuzia'
ktos + ' ma ' + cos+'a.'
'Zuzia ma kota.'
cos = 'zając'
ktos + ' ma ' + cos+'a.'
'Zuzia ma zająca.'
cos == 'kot'
False
cos = 'pies'
ktos + ' ma ' + cos+'a.'
'Zuzia ma piesa.'
zdanie
'Ala ma kota.'

Typ zmiennej

Zmienna sama z siebie nie ma określonego typu. Typ ma przechowywana w niej wartość (trochę podobnie, jak komórka w arkuszu kalkulacyjnym). Nic nie stoi na przeszkodzie, by nowa wartość nadana zmiennej była innego typu, niż wartość przechowywana poprzednio od tą samą nazwą.

a = 'Ala'
type(a)
<type 'str'>
a = 123.55
type(a)
<type 'float'>
a = a == 'Ala'
type(a)
<type 'bool'>
a = int(a)
type(a)
<type 'int'>

Związek między wartościami i zmiennymi jest głębszy, niż się może wydawać na pierwszy rzut oka. Wiedzę na ten temat usystematyzujemy w podrozdziale 10.1.3.

Modyfikowanie wartości zmiennych

Modyfikując wartość zmiennej możemy korzystać z jej poprzedniej wartości.

a = 2
a = a + 2
a = a * 3.0
a
12.0

Służą do tego specjalne warianty operatora przypisania: += -= *= /=. Wykorzystamy je do zsumowania ciągu liczb:

a = 0.0
a += 3
a += 2.5
a += 3.12
a += -0.33
a
8.2900000000000009
# zamienimy wartość podaną w calach na milimetry
a *= 25.4
a
210.566

To samo działa także na danych tekstowych

a = 'Ala'
a += ' '
a += 'i'
a += ' '
a += 'As'
a 
'Ala i As'

Zmiana fragmentu istniejącego napisu nie jest możliwa.

a  = 'Ala i As'
a[0]
'A'
a[0] = 'O'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

Zamiast tego trzeba „zbudować” napis od nowa. Warto przy tym korzystać z istniejących fragmentów:

a  = 'O' + a[1:]
a
'Ola i As'  
b  = a[0:6] + 'O' + a[-1:] + 'a'
b
'Ola i Osa'

Warianty instrukcji przypisania

Python dopuszcza także rozszerzone warianty instrukcji przypisania. Instrukcja

a = b = wartość 

przypisuje dwóm zmiennym (lub dowolnej większej ich liczbie) tę samą wartość. W wyniku takiej operacji zmienne nie tylko otrzymują tę samą wartość, ale będą reprezentować ten sam obiekt (więcej na ten temat powiemy w podrozdziale 10.1.3.).

Kolejny wariant instrukcji przypisania

a, b = wartość1, wartość2 

przypisuje pierwszą wartość pierwszej zmiennej, drugą — drugiej, itd.

Wszystkie wyrażenia z prawej strony są obliczane przed wykonaniem przypisań, więc jeżeli zmienne a lub b występują w obliczanych wyrażeniach, to używane są w nich ich stare wartości. Dlatego w efekcie poniższej instrukcji:

a, b = b, a              

zmienne a i b zamieniają się wartościami.

Takie zachowanie jest charakterystyczne dla Pythona. W językach programowania nie dopuszczających „równoczesnych” przypisań — a są one w większości — zamianę wartości zmiennych a i b realizuje się przy wykorzystaniu zmiennej pomocniczej:

# niech a ma wartość 1, b ma wartość 2
# a: 1, b: 2
p = a	# stan po wykonaniu -- a: 1, b: 2, p: 1
a = b	# stan po wykonaniu -- a: 2, b: 2, p: 1
b = p   # stan po wykonaniu -- a: 2, b: 1, p: 1
# możemy usunąć zmienną pomocniczą p

Bez użycia pomocniczej zmiennej p przypisanie a = b nieodwracalnie usunęłoby wartość początkowo przechowywaną w zmiennej a:

# niech a ma wartość 1, b ma wartość 2
# a: 1, b: 2
a = b	# stan po wykonaniu -- a: 2, b: 2
b = a   # stan po wykonaniu -- a: 2, b: 2

W tej sytuacji instrukcja b = a nie miałaby żadnego realnego znaczenia.

Usuwanie zmiennych

Operacją odwrotną do ustanowienia zmiennej jest jej usunięcie. Nie wnikając w szczegóły możemy stwierdzić, że usunięcie zmiennej skutkuje zwolnieniem zajmowanej przez nią pamięci. Po usunięciu zmiennej operowanie na niej nie jest możliwe (choć w razie potrzeby można powołać nową zmienną o tej samej nazwie).

Zmienne usuwa się za pomocą instrukcji del nazwa_zmiennej.

a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
a = 123
a
123
del a
a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

del jest słowem kluczowym Pythona.

Inną metodą ograniczania zakresu istnienia zmiennych jest deklarowanie ich wewnątrz podprogramu. Zmienna zostanie usunięta z chwilą zakończenia wykonywania podprogramu. Więcej informacji znajdziesz w podrozdziale 7.6.

Funkcje

Funkcja definiuje pewien tok obliczania wartości wynikowej. Funkcja posiada nazwę, której należy użyć w celu obliczenia wyniku.

Wynik obliczeń zależy od podanych wartości argumentów. Liczba argumentów oraz ich znaczenie są określone osobno dla każdej funkcji.

W Pythonie dostępnych jest kilkadziesiąt predefiniowanych funkcji. Są one wymienione w dokumentacji (w wersji 3.x lista funkcji standardowych jest nieco inna).

Przykłady użycia funkcji:

abs(-4.5)	# oblicza wartość bezwzględną
round(4.5)	# zaokrąglenie do wartości całkowitej (wynik jest typu zmiennopozycyjnego)
round(4.55, 1)	# zaokrąglenie do wartości z jedną cyfrą dziesiętną
pow(2, 3)	# to samo co 2**3
max(2, 3, -1)	# zwraca największy z argumentów
len('Ala i As')	# oblicza liczbę znaków w tekście
input('Podaj liczbę ')	# odczytuje wpis użytkownika z wejścia
chr(128)	# generuje znak o podanym kodzie liczbowym

Konwersja typów nie jest funkcją, ale używa się jej podobnie jak funkcji:

int(4.5)
str(1234)
float('123.45')

Wywołanie funkcji jest wyrażeniem, zatem ma wartość. Można go więc użyć w wyrażeniach złożonych, albo zapamiętać jego wynik w zmiennej:

abs(pow(a, 2) - pow(b, 2))
ab = pow(pow(a,2.0) + pow(b,2.0), 0.5)
sameiksy = len('Ala i As')*'x'
wzrost = 0.01*float(input('Twój wzrost [cm] = '))
m = max(a, b, c, d)

Czym jest funkcja w programie?

type(abs)
type(len)
type(input)

Co robi dana funkcja?

help(abs)
help(len)
help(input)

Inne funkcje (pierwiastek? logarytmy? funkcje trygonometryczne?) — jeżeli ich nie ma…

x = 0
y = sin(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  NameError: name 'sin' is not defined

… to trzeba albo skądś je wziąć, albo je sobie napisać.

Na szczęście brać jest skąd (patrz następny podrozdział 5.4.3), a i pisać własne wkrótce się nauczymy (patrz podrozdział 7.6).

Wczytywanie modułów

Co to jest moduł? jest to plik zawierający deklaracje przeznaczone do wykorzystania w programach Pythona. W najprostszym przypadku moduł jest zwykłym plikiem źródłowym Pythona, choć bywa też inaczej.

Wczytanie modułu w najprostszym przypadku następuje za pośrednictwem dyrektywy import:

import nazwa_modułu

Pozwala to użytkownikowi korzystać z obiektów zadeklarowanych w module. Przy opisanym wyżej sposobie wczytywania modułu zdefiniowane w nim obiekty noszą nazwy postaci nazwa_modułu.nazwa_obiektu.

Inne sposoby wczytywania modułów, oparte na wariancie składni polecenia import z wykorzystaniem słów kluczowych from oraz as, umożliwiają dostęp do obiektów zdefiniowanych w module bez poprzedzania ich nazw nazwą modułu, lub z poprzedzeniem ich dowolnie ustaloną nazwą.

Składnia

from nazwa_modułu import *

powoduje wczytanie wszystkich elementów ze wskazanego modułu, przy czym ich nazw w wywołaniach nie będzie trzeba poprzedzać nazwą modułu.

Składnia

import nazwa_modułu as nazwa

powoduje wczytanie wskazanego modułu, i udostępnienie go w programie pod nazwą inną niż domyślna.

import, from i as słowami kluczowymi Pythona.

Ważnym modułem jest math, wchodzący w skład każdej instalacji Pythona. Zawiera on deklaracje wielu przydatnych funkcji matematycznych.

import math
math.sqrt(5.0)
2.2360679774997898
math.pi
3.1415926535897931
math.sin(math.pi/2)
1.0
math.log(1.0)
0.0
math.e
2.7182818284590451
math.log(math.e)
1.0

Python posiada bardzo wiele modułów standardowych, i nieograniczoną liczbę modułów dodatkowych, wymagających zainstalowania. Oprócz tego użytkownik może tworzyć własne moduły.

Moduły są dla programu takimi samymi obiektami, jak wszystkie inne (np. zmienne). Możemy się o tym przekonać, sprawdzając typ wczytanego modułu

type(math)
<type 'module'>

albo listując jego zawartość:

dir(math)
['__doc__', '__file__', '__name__', 'acos', 'asin', 'atan', 'atan2', 
'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 
'frexp', 'hypot', 'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 
'sin', 'sinh', 'sqrt', 'tan', 'tanh']

Dla usunięcia zaimportowanego modułu z pamięci programu wystarczy użyć instrukcji del, np.

del math

Operacja taka nie czyni żadnej krzywdy plikowi, z którego moduł został załadowany.

Instrukcje wejścia i wyjścia

Operatory działań, zmienne reprezentujące pamięć, funkcje, … Taki repertuar środków sprawia, że interpreter Pythona jest bardzo rozbudowanym kalkulatorem.

Jednak do programowania potrzebna jest jeszcze komunikacja z otoczeniem. Dobra praktyka wymaga, by program pobierał dane z zewnątrz i udostępniał wyniki poza swoim środowiskiem. Metod na osiągnięcie tego celu jest sporo. W bieżącym paragrafie omawiamy klasyczne metody wbudowane w język, współpracujące ze standardowym mechanizmem wejścia i wyjścia dostarczanym przez system operacyjny.

Wyjście, czyli wyprowadzanie danych na zewnątrz

Instrukcja print(wyrażenie) wypisuje wartość wyrażenia na konsoli wynikowej. Wyrażeń może być więcej, należy je wtedy oddzielać przecinkami.

a = 'Ala'
b = 'As'
print(a + ' i ' + b)
Ala i As
print(a, b)
Ala As
print(1.0)
1.0
print(1+2+3+4, 1*2*3*4)
10 24

Domyślnie funkcja print wstawia znak nowego wiersza (Enter) po ostatniej wydrukowanej frazie. Przekazanie jej dodatkowego argumentu end = '' sprawi, że znak nowego wiersza zostanie pominięty.

Zwróćmy uwagę, że funkcja print w pewien sposób formatuje wydruk:

print jest słowem kluczowym Pythona do wersji 2.x włącznie. Nawiasy wokół drukowanych wyrażeń nie były wymagane przez składnię.

W Pythonie 3 słowo kluczowe print nie istnieje. Została za to wprowadzona funkcja o tej samej nazwie. Zatem wyrażenia przeznaczone do wydrukowania za pomocą instrukcji print trzeba przekazywać w nawiasach:

print(wyrażenie)
print(wyrażenie1, wyrażenie2)

Wejście, czyli wprowadzanie danych z zewnątrz

Najprostszym sposobem pobrania przez program wartości zewnętrznej jest użycie funkcji input(). Wynik przekazywany przez funkcję input() jest zawsze tekstem.

W Pythonie 2 istniała funkcja raw_input(), która zachowywała się się tak, jak funkcja input() znana z wersji 3. Natomiast funkcja o nazwie input() interpretowała tekst wprowadzony przez użytkownika, a typ wartości wynikowej był ustalany w czasie tej interpretacji. Dawało to możliwość niekontrolowanego wykorzystania działania przez operatora programu i stało się bezpośrednią przyczyną wprowadzenia zmiany.

Wartość wpisaną przez użytkownika zazwyczaj chcemy gdzieś zapamiętać.

nazwa = input()	# pobiera tekst od użytkownika i przypisuje go obiektowi nazwa

Jak argument funkcji input() można podać dowolny tekst. Zostanie on przedstawiony użytkownikowi jako komunikat zachęcający do wpisania wartości.

nazwa = input(komunikat)	# to samo co input(), tylko przed pobraniem tekstu przekazuje komunikat dla użytkownika
x = input('Ile masz lat? ')
Ile masz lat? 20
print('Wiem, że masz', x, 'lat')
Wiem, że masz 20 lat
x = input('Jak masz na imię? ')
Jak masz na imię? Marcin
print('Wiem, że masz na imię', x)
Wiem, że masz na imię Marcin

Inne przydatne instrukcje

Funkcja dir(obiekt) pokazuje listę właściwości obiektu, np.

dir(math)
dir('ala')
dir(1)

Funkcja type(obiekt) informuje o typie obiektu, np.

type(1)
type('Ala ma Asa')
type(max)
type(math)
type(math.pi)

Funkcja help(obiekt) udostępnia podstawową dokumentację obiektu, np.

help()
help(math)
help(math.sin)
help(abs)

Python jako interpreter gotowego programu

Program źródłowy Pythona jest ciągiem poleceń zapisanych w pliku tekstowym po jednym poleceniu w każdym wierszu.

instrukcja
instrukcja
instrukcja
instrukcja

Dopuszczalne jest także oddzielanie średnikami instrukcji zapisanych w jednym wierszu.

instrukcja; instrukcja
instrukcja; instrukcja
instrukcja

Zapisany tym sposobem ciąg instrukcji tworzy blok. W ramach jednego bloku instrukcje są wykonywane po kolei.

Jak zobaczymy w następnych rozdziałach, w Pythonie możliwe jest zagnieżdżanie bloków instrukcji. Jest ono wykorzystywane przy sterowaniu przebiegiem programu. Podział na bloki następuje za pomocą głębokości wcięć wierszy kodu źródłowego.

Do robienia wcięć mogą służyć znaki spacji lub znaki tabulacji, jednak nie należy ich mieszać ze sobą. Głębokości wcięć są dowolne, ale muszą być takie same w obrębie jednego bloku. Na razie po prostu piszmy instrukcje jedna pod drugą, unikając białych znaków na początku wiersza.

Używanie znaków spacji i tabulacji w jednym pliku jest zawsze nieeleganckie. Pociąga za sobą również niebezpieczeństwo błędnej interpretacji, gdyż różne edytory mogą przedstawiać tabulator za pomocą odmiennych głębokości skoku. Dlatego w Pythonie 3 wymaganie konsekwentnego stosowania tylko jednego z tych znaków zostało podniesione do rangi reguły składniowej.

Jeżeli instrukcja jest na tyle długa, że warto ją podzielić na kilka wierszy dla zachowania czytelności, to wstawiamy symbol \ na końcu wiersza dla oznaczenia, że instrukcja jeszcze się nie zakończyła.

# podział długiej instrukcji na wiersze zwiększa czytelność kodu
ab = math.sqrt( (a[0] - b[0])**2 + \
                (a[1] - b[1])**2   )

W takim przypadku wcięcie drugiego i następnych wierszy nie jest istotne.

Nie ma znaczenia, jakim edytorem się posłużymy podczas zapisywania poleceń; ważny jest jedynie znakowy format zapisu. Dobrym zwyczajem jest nadawanie plikowi źródłowemu nazwy z rozszerzeniem py.

Przy interaktywnym korzystaniu z konsoli Pythona nie było widać wielu korzyści z funkcji print. Zbliżony skutek (nie licząc interpretacji znaków specjalnych) dało się uzyskać wpisując wyrażenie bezpośrednio przy znaku zgłoszenia:

a = 'Ala'
b = 'As'
a + ' i ' + b
Ala i As
print(a + ' i ' + b)
Ala i As
a + '\ti\t' + b
Ala\ti\tAs
print(a + '\ti\t' + b)
Ala	i	As

W trakcie interpretacji pliku źródłowego jest inaczej. Wpisywane wyrażenia są co prawda obliczane, ale nie są nigdzie drukowane; ich wartość nie jest też nigdzie zapamiętywana.

Żeby się o tym przekonać, zróbmy prosty eksperyment. Za pomocą dowolnego nieformatującego edytora utwórzmy plik tekstowy o następującej zawartości:

a = 'Ala'
b = 'As'
a + ' i ' + b

i zapiszmy go pod nazwą proba1.py. Po uruchomieniu polecenia

c:\Users\Ja\testy> python proba1.py

nie dostaniemy od interpretera żadnej informacji wynikowej.

Tymczasem funkcja print, tak samo jak w trybie interaktywnym, przesyła dane do standardowego pliku wynikowego. W konsekwencji pojawiają się one na urządzeniu wyjściowym, np. na terminalu systemowym lub w oknie środowiska programistycznego przeznaczonym do prezentacji danych wynikowych.

Wykonajmy drugie doświadczenie: poniższy tekst

a = 'Ala'
b = 'As'
print(a + ' i ' + b)

zapiszmy w pliku proba2.py. Po uruchomienia programu otrzymamy na urządzeniu wyjściowym wydruk:

c:\Users\Ja\testy> python proba2.py
Ala i As

Uruchamianie programu źródłowego z poziomu interpretera Pythona

c:\Users\Ja\testy> python
import nazwa

Uruchamianie programu tą metodą jest szczególnym przypadkiem importowania modułu.

Pisząc w przykładach polecenie systemowe python zakładamy, że system czytelnika został skonfigurowany zgodnie z zaleceniami wymienionymi w podrozdziale 5.1.6. poświęconemu instalacji oprogramowania.

Dociekliwi zauważą, że podczas importowania modułu z pliku py następuje jego kompilacja. Jej wynikiem jest plik binarny o rozszerzeniu pyc (‘Python Compiled’). Taki plik zawiera cały kod programu w postaci binarnej. Można go uruchamiać analogicznymi sposobami, jak kod źródłowy, bez konieczności posiadania tego ostatniego.

Uruchamianie programu źródłowego z poziomu konsoli systemowej

Ta metoda uruchamiania wywołuje z poziomu powłoki systemowej interpreter języka Python z nazwą programu jako argumentem. Możliwe jest również użycie nazwy programu źródłowego jako polecenia.

W systemach Windows (cmd, powershell)

c:\Users\Ja\testy> c:\python26\python nazwa.py

W przypadku, kiedy kartoteka w której zainstalowano Pythona jest wpisana na listę ścieżek poszukiwania programów (PATH; patrz podrozdział 5.1. — nie dzieje się to podczas domyślnej instalacji), wystarczy polecenie postaci

c:\Users\Ja\testy> python nazwa.py

Natomiast wykorzystanie rozszerzonej składni interpretera systemowego, biorącej pod uwagę zarejestrowane w systemie powiązania rozszerzeń nazw plików z obsługującą aplikacją, pozwala uruchamiać program poleceniem postaci

c:\Users\Ja\testy> nazwa.py

W przypadku, kiedy w konfiguracji systemu rozszerzenie nazwy .py zostało zadeklarowane jako wykonywalne, można je pominąć:

c:\Users\Ja\testy> nazwa

W systemach uniksowych (bash, csh i inne)

$ python3 nazwa.py

przy założeniu, że python3 jest nazwą programu uruchamiającego interpreter Pythona.

Interpretery poleceń w systemach uniksowych pozwalają uprościć uruchamianie skryptów za pomocą techniki zwanej shebang: jeżeli plikowi źródłowemu nadamy atrybut wykonywalności, i w jego pierwszym wierszu umieścimy wpis

#!/usr/bin/python3

o ile jesteśmy pewni ścieżki do interpretera, lub

#!/usr/bin/env python3

o ile wolimy pozostawić systemowi odnalezienie pliku interpretera, to plik ten będzie się dało uruchamiać poleceniem

$ ./nazwa.py

z poziomu powłoki systemowej (np. bash). Trick ten dotyczy wielu języków interpretowanych, nie tylko Pythona.

Dla interpretera Pythona wpis ten jest zwykłym komentarzem.

Uruchamianie programu źródłowego z poziomu środowiska graficznego

W tej metodzie polecenie postaci python plik.py jest wywoływane w reakcji na manipulacje obiektami środowiska użytkowego.

Funkcja Otwórz (ew. Uruchom) wywołana na ikonie pliku źródłowego nazwa.py np. przez podwójne kliknięcie, <Enter> lub przez menu kontekstowe.

Jeżeli uruchamiany kod jest programem terminalowym, to przydzielone mu w środowisku graficznym okno zostanie zamknięte natychmiast po wykonaniu ostatniej instrukcji. Dlatego programy tego typu lepiej uruchamiać z poziomu terminala znakowego. Można też tak zaprojektować program, żeby po wydrukowaniu wyników zaczekał z zakończeniem pracy na reakcję użytkownika (np. wykonując instrukcję input()).

Uruchamianie programu źródłowego z poziomu edytora kodu

Niektóre zaawansowane edytory dają możliwość uruchamiania tworzonych w ich sesji programów.

SciTE

SciTE obsługuje podświetlanie i zwijanie elementów składni Pythona. Po dostarczeniu odpowiedniego pliku konfiguracyjnego może także wyświetlać podpowiedzi dotyczące poleceń.

Ponadto SciTE pozwala uruchamiać programy bezpośrednio z poziomu edytora za pomocą funkcji menu:

Widok/[x]Pole wyników
Narzędzia/Uruchom (F5)

lub jej odpowiednika w aktualnym języku interfejsu użytkowego. To dobrodziejstwo wymaga, by ścieżka dostępu do interpretera Pythona była wpisana do ścieżek systemowych (PATH; patrz podrozdział 5.1. poświęcony instalacji).

W systemach uniksowych SciTE nie obsługuje wprowadzania danych wejściowych do programu przez okno Pole Wyników. Można tylko odczytywać z niego wyniki.

Notepad++

Możliwości Notepad++ są zbliżone do możliwości SciTE; oba edytory korzystają z tej samej biblioteki kodu źródłowego, udostępniającej komponent edycyjny o nazwie Scintilla. Notepad++ wymaga skonfigurowania, jeżeli chodzi o opcję uruchamiania programu. Robi się to wypełniając formularz dialogowy wywoływany z menu programu:

Run/Run 
    python $(FULL_CURRENT_PATH) 
Save
    Name: Python
    Ctrl [x]
	     + Shift [x] + [Klawisz]
    Alt [x]

(W przypadku, kiedy ścieżka do interpretera Pythona nie jest opisana w konfiguracji systemu, w powyższym wpisie nazwę polecenia python trzeba zastąpić pełną ścieżką, np. c:\python27\python.exe).

Uruchomienie bieżącego programu Pythona w terminalu tekstowym będzie wtedy możliwe przez opcję menu

Run/Python

lub przez zadeklarowany skrót klawiszowy.

Inną sensowną możliwością jest użycie dodatku przygotowanego dla programu Notepad++, który umożliwia uruchamianie skryptów napisanych w Pythonie.

Bluefish

Także ten edytor jest dość wygodny przy pisaniu prostych programów w Pythonie. Opcję uruchamiania kodu źródłowego trzeba samemu skonfigurować:

Edycja/Ustawienia/Programy zewnętrzne/Programy użytkowe i filtry/
    Etykieta: Python
    Polecenie: xterm -e "python '%s'; read 'naciśnij Enter...'"

Uruchomienie kodu w zewnętrznym terminalu będzie wtedy wymagać użycia opcji

Zewnętrzne/Polecenia/Python

której warto przypisać skrót klawiszowy (np. <F5>).

Podobnym sposobem da się zaprogramować uruchamianie zewnętrznego debuggera (np. WinPDb) z poziomu menu Bluefish.

Emacs

Edytor Emacs wyposażony jest we wszelkie udogodnienia służące tworzeniu i uruchamianiu kodu komputerowego napisanego w praktycznie dowolnym języku — w tym także w Pythonie.

Uruchomienie programu z poziomu Emacsa przebiega następująco: po załadowaniu pliku źródłowego z rozszerzeniem .py opcje menu

Python/Start Interpreter
Python/Eval buffer

odpowiednio: inicjują okno Emacsa z konsolą interpretera i uruchamiają program z załadowanego pliku. Wejście i wyjście tekstowe odbywa się przez konsolę w oknie.

Uruchamianie programu źródłowego z poziomu środowiska programistycznego

Środowisko programistyczne różni się od edytora programisty przede wszystkim tym, że pozwala uruchamiać kod źródłowy w trybie diagnostycznym i w znacznym stopniu na bieżąco kontrolować jego wykonywanie.

IDLE

IDLE jest graficznym środowiskiem do edycji i uruchamiania kodu źródłowego, dołączanym do każdej dystrybucji Pythona. Dlatego warto je znać, choć pod względem prostoty użytkowania przegrywa z innymi podobnymi narzędziami.

Plik źródłowy wczytany do edytora uruchomimy za pośrednictwem opcji

Run/Run module (F5)

PythonWin

PythonWin jest pełnym środowiskiem uruchomieniowym, wyposażonym w niezły edytor (korzystający, podobnie jak SciTE i Notepad++, z projektu Scintilla), zintegrowaną konsolę Pythona i debugger. Działa w systemach operacyjnych Windows.

Program w aktywnym oknie edycyjnym uruchamiamy za pomocą opcji menu

File/Go (F5)

lub ikonki „z biegnącym ludzikiem” na listwie narzędzi.

Pewną osobliwością PythonWin jest uruchamianie kolejnych programów w ramach jednej sesji interpretera. Powoduje to, że skutki działania programu w pamięci pozostają widoczne dla programów uruchamianych w następnej kolejności. Fakt ten może utrudniać znalezienie przyczyn błędów w testowanych za pomocą PythonWin programach.

Inne

Inne środowiska, jak WingIDE, Komodo, WinPDb mają swoje, nieco odmienne, lecz analogiczne sposoby uruchamiania wczytanego programu.

Uruchamianie programu źródłowego z poziomu środowisk użytkowych

W niektórych środowiskach użytkowych język Python pełni rolę języka makropoleceń. Oznacza to, że istnieje możliwość uruchomienia takiego programu bez opuszczania środowiska, i że działanie takiego programu rozszerza możliwości środowiska o nową funkcjonalność.

Odsyłacze w przyszłość: OpenOfficepodrozdział 11.4.4., Gnumericpodrozdział 11.4.6., inne.

Pytania kontrolne

  1. Co to są słowa kluczowe języka programowania?
  2. Co to są instrukcje języka programowania?
  3. Jak uruchomić interpreter Pythona?
  4. W jaki sposób w Pythonie określany jest typ wyrażeń (chodzi o typy proste)?
  5. Jak użyć interpretera Pythona jako kalkulatora?
  6. Jak uruchomić gotowy program źródłowy napisany w Pythonie?
© Copyright 2000–2024 by Jan Jełowicki, Katedra Matematyki Uniwersytetu Przyrodniczego we Wrocławiu
Ostatnia modyfikacja w kwietniu 2024
janj@aqua.up.wroc.pl
http://karnet.up.wroc.pl/~jasj