Języki skryptowe Python

advertisement
Języki skryptowe ­ Python
Wykład 2 ­ Pierwsze kroki
Janusz Szwabiński
Plan wykładu:
Uruchamianie programów
Typowanie dynamiczne
Interpreter i kompilacja
Narzędzia
Python w pigułce
Kilka słów o składni
Uruchamianie programów
Poniżej znajduje się prosty program (skrypt) napisany w Pythonie:
In [1]:
# symbolem "#" oznaczamy komentarz (wiersz ignorowany przez interpreter Pythona)
# Lista instrumentów muzycznych
instruments = ['Saksofon', 'Perkusja', 'Gitara']
# dla każdej nazwy na liście
for item in instruments:
# wypisz tę nazwę na ekranie
print(item)
Saksofon
Perkusja
Gitara
W powyższym przykładzie instruments to nazwa zmiennej, której przypisano listę nazw instrumentów.
Słowo kluczowe for oznacza pętlę po elementach listy ­ w każdym powtórzeniu zmiennej instrument
przypisana jest inna nazwa z tej listy.
Tryb skryptowy
Przedstawiony kod został uruchomiony bezpośrednio w notatniku IPythona, który wykorzystuję do prezentacji
w ramach wykładu. Inna możliwość to zapisanie programu do pliku tekstowego z rozszerzeniem .py i
uruchomienie go bezpośrednio z wiersza poleceń:
W systemach z rodziny Windows rozszerzenia plików .py, . pyw, . pyc i . pyo są przypisane
automatycznie do interpretera Pythona podczas instalacji. Dlatego klikając w ikonę pliku, również go
uruchomimy (pliki .pyw uruchamiane są z alternatywną wersją interpretera, który nie otwiera okna konsoli).
Tryb interaktywny
Interpretera Pythona możemy używać w trybie interaktywnym. Interpreter zachęca wtedy do podania kolejnej
instrukcji za pomocą znaku zachęty, zwykle w postaci >>>. Znak zmienia się na ..., gdy interpreter wymaga
od nas kontynuacji instrukcji w następnej linii.
W systemach Windows można ponadto uruchomić interpreter Pythona w trybie interaktywnym korzystając z
ikony Python (command line).
Trybu interaktywnego używa się do:
obliczeń matematycznych
testowania hipotez
operacji na danych i wizualizacji danych
testowania i modyfikowania wycinków kodu przed wstawieniem ich do wiekszych programów
analizowania stanu obiektów w pamięci
i wielu innych
Wbudowane typy danych (wybrane)
numeryczne
int ­ liczby całkowite
float ­ liczby zmiennopozycyjne (rzeczywiste)
complex ­ liczby zespolone
sekwencyjne
list ­ listy
tuple ­ krotki (tzn. listy, których nie można zmieniać)
range ­ niezmienne sekwencje liczb, wykorzystywane w pętlach for
tekstowe
str ­ ciągi znaków Unicode
zbiory
set ­ nieuporządkowane kolekcje elementów
frozenset ­ j.w., ale nie można zmieniać ich zawartości
mapowania
dict
In [2]:
import sys
In [3]:
sys.float_info
Out[3]:
sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_ex
p=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307,
dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, round
s=1)
In [4]:
sys.int_info
Out[4]:
sys.int_info(bits_per_digit=30, sizeof_digit=4)
In [6]:
sys.maxsize
Out[6]:
9223372036854775807
In [7]:
sys.maxsize + 10
Out[7]:
9223372036854775817
Typowanie dynamiczne
Jedną z ważnych cech Pythona jest typowanie dynamiczne
(https://pl.wikipedia.org/wiki/Typowanie_dynamiczne), które polega na tym, że typy przypisywane są do
wartości przechowywanych w zmiennych dopiero w trakcie działania programu. Interpreter ustala typy na
podstawie samych wartości oraz metod udostępnionych przez obiekt. W języku angielskim takie typowanie
określa się czasami jako Duck Typing. Nazwa wywodzi się z tzw. testu kaczki, który przypisywany jest J. W.
Rileyowi (źródło: Wikipedia (https://en.wikipedia.org/wiki/Duck_typing)):
When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call
that bird a duck.
Warto wspomnieć również o tym, że typowanie w Pythonie jest silne
(https://pl.wikipedia.org/wiki/Typowanie_silne), tzn. interpreter wykonuje automatyczną konwersję jedynie
między typami, które są silnie ze sobą powiązane (np. int i long int). Wszelkie operacje między
niekompatybilnymi typami mogą się odbyć jedynie po jawnej konwersji zmiennej lub zmiennych do jednego
typu.
In [9]:
1+3
Out[9]:
4
In [10]:
1 + 3.0
Out[10]:
4.0
In [11]:
"Hello" + " world"
Out[11]:
'Hello world'
In [12]:
"Hello" * 3
Out[12]:
'HelloHelloHello'
In [13]:
"Hello" + 3
-------------------------------------------------------------------------TypeError
Traceback (most recent ca
ll last)
<ipython-input-13-888f0e761d75> in <module>()
----> 1 "Hello" + 3
TypeError: Can't convert 'int' object to str implicitly
Dla porównania zobaczmy, jak ten ostatni przykład będzie wyglądał w JavaScripcie:
O takim języku mówimy, że jest słabo typowany.
Interpreter i kompilacja
Kod źródłowy jest parsowany i tłumaczony do kodu bajtowego (ang. bytecode) Pythona, czyli ciągu instrukcji
do wykonania zapisanych w formacie binarnym. Kod bajtowy można przenosić między różnymi systemami
operacyjnymi i uruchamiać bez wyjściowego pliku źródłowego.
Kod bajtowy jest domyślnie zapisywany na dysku. Dlatego przy następnym uruchomieniu programu nie ma
konieczności ponownego parsowania skryptu i kompilowania go. W ten sposób skrócony zostaje czas
uruchomienia programu.
Kod bajtowy przechowywany jest w plikach .pyc (wersja normalna) lub .pyo (wersja zoptymalizowana).
Wersja zoptymalizowana wymaga uruchomienia interpretera z flagą -O.
Narzędzia
Istnieje bardzo dużo narzędzi, które ułatwiają programowanie w Pythonie. Można wśród nich znaleźć
programy zastępujące powłokę, edytory wspierające składnię czy też zintegrowane środowiska
programistyczne (ang. Integrated Development Environments, IDEs).
Zamiast powłoki
Do pracy interaktywnej, zamiast oryginalnej powłoki Pythona, możemy użyć programów PyCrust (w nowszej
wersji Py (http://www.wxpython.org/py.php)) lub IPython (http://ipython.org/) .
PyCrust to graficzna powłoka, która między innymi oferuje uzupełnianie składni, podgląd przestrzeni nazw i
historię poleceń. Po włączeniu programu do projektu WxPython w najnowszych dystrybucjach można go
znaleźć pod nazwą Py.
IPython ma możliwości podobne do PyCrust, jednak może pracować w trybie tekstowym. Powłoka oferuje
m.in. kolorowanie składni, uzupełnianie składni, historię. Do wersji 3.0 IPython oferował również uruchamiane
w przeglądarce WWW notatniki, które pozwalały na mieszanie wykonywalnego kodu źródłowego z tekstem o
dość zaawansowanym formatowaniu. Od wersji 4.0 IPython to głównie powłoka interaktywna Pythona, a cała
funkcjonalność związana z notatnikami została przeniesiona do projektu Jupyter (https://jupyter.org/).
Edytory tekstowe
Decydując się na pracę z Pythonem w trybie "skryptowym", potrzebujemy w zasadzie tylko edytora
tekstowego. Dobrze, gdyby wspierał on składnię Pythona. W systemach linuksowych możemy korzystać z
praktycznie każdego edytora w trybie tekstowym (np. vi, emacs, nano) lub graficznym (gedit, kate, geany).
Ostatni ze przedstawionych powyżej edytorów, Geany, dostępny jest również w wersjach dla Windows i Mac
OS. Innym edytorem dostępnym pod Linuksem i na Windows jest SciTE (http://www.scintilla.org/SciTE.html).
Bardzo dobrym edytorem dla programistów pod Windowsem jest Notepad++ (http://notepad­
plus.sourceforge.net/br/site.htm). Jeśli spodoba się nam ten edytor, a pod innymi systemami chcielibyśmy
mieć podobny, można pomyśleć o zainstalowaniu Notepadqq (http://notepadqq.altervista.org/wp/).
IDE
Zintegrowane środowiska programistyczne (ang. Integrated Development Environment) to pakiety
oprogramowania oferujące wiele narzędzi przydatnych programiście ­ od edytorów z kolorowaniem i
uzupełnianiem składni, poprzez przeglądarki kodów źródłowych, zintegrowaną powłokę po debugger (lub
przynajmniej nakładkę graficzną na niego). Poniżej znajdują się wybrane IDEs dla Pythona:
Idle (https://docs.python.org/2/library/idle.html)
PyScripter (http://code.google.com/p/pyscripter/)
SPE (http://pythonide.blogspot.com/) (Stani's Python Editor)
Eric (http://eric­ide.python­projects.org/)
PyDev (http://pydev.org/) (plug­in do Eclipse)
Budowanie pakietów binarnych
Jeżeli myślimy o dystrybucji programów napisanych w Pythonie, warte uwagi mogą okazać się programy
służące do budowania pakietów binarnych, złożonych z kodu bajtowego, interpretera i wszystkich
potrzebnych zależności. Stworzenie takiego pakietu umożliwia uruchomienie naszego programu na
komputerze bez zainstalowanego Pythona. Dodatkowo (do pewnego stopnia) chroni kod źródłowy.
Wśród tego typu aplikacji mamy do wyboru m.in.:
py2exe (tylko dla Windows)
cx_Freeze (przenośne)
Platformy programistyczne (ang. frameworks)
Platformy programistyczne to szkielety do budowy aplikacji. Definiują strukturę aplikacji oraz ogólny
mechanizm jej działania, a także dostarczają zestawy komponentów i bibliotek ogólnego przeznaczenia do
wykonywania określonych zadań.
Najbardziej znane platformy dla Pythona:
aplikacje webowe: Django, TurboGears, Zope i web2py
GUI: wxPython, PyGTK i PyQt
obliczenia naukowe: NumPy i SciPy
przetwarzanie obrazów: PIL
wizualizacje 2D: Matplotlib i SVGFig
wizualizacje 3D: Visual Python, PyOpenGL i Python Ogre
mapowanie obiektowo­relacyjne: SQLAlchemy i SQLObject
Python w pigułce
Liczby całkowite
Zacznijmy od prostych działań na liczbach całkowitych:
In [14]:
2+2
Out[14]:
4
In [15]:
(50-5*6)/4 #w pythonie 2.7 wynik byłby całkowity!!!
Out[15]:
5.0
In [16]:
(50-5*6)//4
Out[16]:
5
In [17]:
7/3 # w pythonie 2.7 wynik będzie 2
Out[17]:
2.3333333333333335
In [18]:
-7/3
Out[18]:
-2.3333333333333335
In [19]:
7//3
Out[19]:
2
In [21]:
szer = 10
wys = 30.0
pole = szer * wys
print(pole)
300.0
In [22]:
type(szer)
Out[22]:
int
In [23]:
type(wys)
Out[23]:
float
In [24]:
a=b=c=0
print(a, b, c)
000
In [25]:
a, b, c = 1, 2, 3 # pythonowy idiom
print (a,b,c)
123
In [26]:
9**2
Out[26]:
81
In [27]:
_/3 # _ to ostatni wynik
Out[27]:
27.0
Funkcje użytkownika
Możliwości Pythona możemy rozszerzać, definiując własne funkcje:
In [28]:
def silnia(x):
if x<=1:
return 1
return x*silnia(x-1)
In [29]:
silnia(4)
Out[29]:
24
In [30]:
silnia(17)
Out[30]:
355687428096000
In [31]:
silnia(100)
Out[31]:
9332621544394415268169923885626670049071596826438162146859296389521
7599993229915608941463976156518286253697920827223758251185210916864
000000000000000000000000
I jeszcze raz, informacja systemowa dotycząca typu całkowitego:
In [39]:
sys.maxsize
Out[39]:
9223372036854775807
W przeciwieństwie do Pythona 2.7, w wersji 3.5 nie mamy największej liczby w typie int. Jest ona w
praktyce ograniczona jedynie możliwościami komputera. Powyższa liczba stanowi maksymalny rozmiar
sekwencji i odpowiada największej możliwej do przedstawienia liczbie naturalnej w typie int w Pythonie 2.7.
Liczby zmiennoprzecinkowe
In [32]:
7/3
Out[32]:
2.3333333333333335
In [33]:
7.0/3
Out[33]:
2.3333333333333335
In [34]:
float(7)
Out[34]:
7.0
In [35]:
x = 1.1*10**308
In [36]:
2*x
Out[36]:
inf
In [37]:
y = 2*x
In [38]:
1/y
Out[38]:
0.0
Kilka informacji systemowych o liczbach zmiennoprzecinkowych:
In [37]:
import sys
sys.float_info
Out[37]:
sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_ex
p=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307,
dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, round
s=1)
Liczby zespolone
In [40]:
1j * 1J
Out[40]:
(-1+0j)
In [41]:
complex(1,2)
Out[41]:
(1+2j)
In [42]:
complex(1,2)*complex(2,1)
Out[42]:
5j
In [43]:
(1+2j)*(2+j) #nie do końca jak na papierze
-------------------------------------------------------------------------NameError
Traceback (most recent ca
ll last)
<ipython-input-43-ce6b82197b42> in <module>()
----> 1 (1+2j)*(2+j) #nie do końca jak na papierze
NameError: name 'j' is not defined
In [44]:
(1+2j)*(2+1j)
Out[44]:
5j
In [45]:
a = 1.5 + 0.5j
In [46]:
a.real
Out[46]:
1.5
In [47]:
a.imag
Out[47]:
0.5
In [48]:
float(a)
-------------------------------------------------------------------------TypeError
Traceback (most recent ca
ll last)
<ipython-input-48-93d25633ffc4> in <module>()
----> 1 float(a)
TypeError: can't convert complex to float
In [49]:
abs(a) #sqrt(a.real**2 + a.imag**2)
Out[49]:
1.5811388300841898
Wbudowana pomoc
In [50]:
help(a)
Help on complex object:
class complex(object)
| complex(real[, imag]) -> complex number
|
| Create a complex number from a real part and an optional imagin
ary part.
| This is equivalent to (real + imag*1j) where imag defaults to
0.
|
| Methods defined here:
|
| __abs__(self, /)
|
abs(self)
|
| __add__(self, value, /)
|
Return self+value.
|
| __bool__(self, /)
|
self != 0
|
| __divmod__(self, value, /)
|
Return divmod(self, value).
|
| __eq__(self, value, /)
|
Return self==value.
|
| __float__(self, /)
|
float(self)
|
| __floordiv__(self, value, /)
|
Return self//value.
|
| __format__(...)
|
complex.__format__() -> str
|
|
Convert to a string according to format_spec.
|
| __ge__(self, value, /)
|
Return self>=value.
|
| __getattribute__(self, name, /)
|
Return getattr(self, name).
|
| __getnewargs__(...)
|
| __gt__(self, value, /)
|
Return self>value.
|
| __hash__(self, /)
|
Return hash(self).
|
| __int__(self, /)
|
int(self)
|
| __le__(self, value, /)
|
Return self<=value.
|
| __lt__(self, value, /)
|
Return self<value.
|
| __mod__(self, value, /)
|
Return self%value.
|
| __mul__(self, value, /)
|
Return self*value.
|
| __ne__(self, value, /)
|
Return self!=value.
|
| __neg__(self, /)
|
-self
|
| __new__(*args, **kwargs) from builtins.type
|
Create and return a new object. See help(type) for accurat
e signature.
|
| __pos__(self, /)
|
+self
|
| __pow__(self, value, mod=None, /)
|
Return pow(self, value, mod).
|
| __radd__(self, value, /)
|
Return value+self.
|
| __rdivmod__(self, value, /)
|
Return divmod(value, self).
|
| __repr__(self, /)
|
Return repr(self).
|
| __rfloordiv__(self, value, /)
|
Return value//self.
|
| __rmod__(self, value, /)
|
Return value%self.
|
| __rmul__(self, value, /)
|
Return value*self.
|
| __rpow__(self, value, mod=None, /)
|
Return pow(value, self, mod).
|
| __rsub__(self, value, /)
|
Return value-self.
|
| __rtruediv__(self, value, /)
|
Return value/self.
|
| __str__(self, /)
|
Return str(self).
|
| __sub__(self, value, /)
|
Return self-value.
|
| __truediv__(self, value, /)
|
Return self/value.
|
| conjugate(...)
|
complex.conjugate() -> complex
|
|
Return the complex conjugate of its argument. (3-4j).conjug
ate() == 3+4j.
|
| --------------------------------------------------------------------| Data descriptors defined here:
|
| imag
|
the imaginary part of a complex number
|
| real
|
the real part of a complex number
Biblioteka standardowa
In [51]:
import math #importujemy moduł matematyczny z biblioteki standardowej
In [52]:
dir(math)
#zawartość modułu
Out[52]:
['__doc__',
'__loader__',
'__name__',
'__package__',
'__spec__',
'acos',
'acosh',
'asin',
'asinh',
'atan',
'atan2',
'atanh',
'ceil',
'copysign',
'cos',
'cosh',
'degrees',
'e',
'erf',
'erfc',
'exp',
'expm1',
'fabs',
'factorial',
'floor',
'fmod',
'frexp',
'fsum',
'gamma',
'hypot',
'isfinite',
'isinf',
'isnan',
'ldexp',
'lgamma',
'log',
'log10',
'log1p',
'log2',
'modf',
'pi',
'pow',
'radians',
'sin',
'sinh',
'sqrt',
'tan',
'tanh',
'trunc']
In [53]:
help(math.ceil)
Help on built-in function ceil in module math:
ceil(...)
ceil(x)
Return the ceiling of x as an int.
This is the smallest integral value >= x.
In [54]:
math.pi
Out[54]:
3.141592653589793
In [55]:
math.cos(math.pi/2) #powinno być zero
Out[55]:
6.123233995736766e-17
In [56]:
math.e
Out[56]:
2.718281828459045
In [57]:
math.log(math.e)
#logarytm naturalny
Out[57]:
1.0
In [58]:
math.sqrt(8)
Out[58]:
2.8284271247461903
In [59]:
math.sqrt(-8)
-------------------------------------------------------------------------ValueError
Traceback (most recent ca
ll last)
<ipython-input-59-d928edca9d4e> in <module>()
----> 1 math.sqrt(-8)
ValueError: math domain error
In [60]:
import cmath
cmath.sqrt(-8)
Out[60]:
2.8284271247461903j
In [61]:
dir(cmath)
Out[61]:
['__doc__',
'__file__',
'__loader__',
'__name__',
'__package__',
'__spec__',
'acos',
'acosh',
'asin',
'asinh',
'atan',
'atanh',
'cos',
'cosh',
'e',
'exp',
'isfinite',
'isinf',
'isnan',
'log',
'log10',
'phase',
'pi',
'polar',
'rect',
'sin',
'sinh',
'sqrt',
'tan',
'tanh']
Listy
In [4]:
numbers = [1, 2, 3, 4, 5]
In [5]:
numbers[3]
Out[5]:
4
In [6]:
numbers[1:3]
Out[6]:
[2, 3]
In [7]:
numbers.append(6)
In [8]:
numbers
Out[8]:
[1, 2, 3, 4, 5, 6]
In [9]:
squares = [i**2 for i in numbers]
In [10]:
squares
Out[10]:
[1, 4, 9, 16, 25, 36]
Pętle
In [11]:
for i in numbers:
print(i,i**2)
11
24
39
4 16
5 25
6 36
Wyrażenia warunkowe
In [12]:
for i in numbers:
if(i%2==0):
print(i)
2
4
6
Zbiory
In [13]:
z1 = set('banan')
z2 = set('ananas')
In [14]:
print(z1,z2)
{'b', 'a', 'n'} {'s', 'a', 'n'}
In [16]:
z1 | z2
Out[16]:
{'a', 'b', 'n', 's'}
In [17]:
z1 - z2
Out[17]:
{'b'}
In [18]:
z1 & z2
Out[18]:
{'a', 'n'}
In [19]:
z1 ^ z2
Out[19]:
{'b', 's'}
Łańcuchy znaków
In [20]:
tekst = "To jest przykład zdania w języku polskim."
In [21]:
tekst.split()
Out[21]:
['To', 'jest', 'przykład', 'zdania', 'w', 'języku', 'polskim.']
In [22]:
slowa = tekst.split()
In [23]:
'&'.join(slowa)
Out[23]:
'To&jest&przykład&zdania&w&języku&polskim.'
Operacje na plikach
In [24]:
f = open('mojplik.txt','w')
In [25]:
f.write('Pierwszy wiersz.\n')
Out[25]:
17
In [26]:
f.write('Drugi wiersz.')
Out[26]:
13
In [27]:
f.close()
In [28]:
f = open('mojplik.txt','r')
for line in f:
print(line)
f.close()
Pierwszy wiersz.
Drugi wiersz.
Formatowanie wyjścia
In [29]:
template = '{0}{1}{0}'
In [30]:
template.format('abra','cad')
Out[30]:
'abracadabra'
In [31]:
coord = (3,5)
'X: {0[0]}; Y: {0[1]}'.format(coord)
Out[31]:
'X: 3; Y: 5'
Kilka słów o składni
Program (skrypt) w Pythonie składa się z wierszy, które zawierają sekwencje elementów języka. Ze wzgledu
na czytelność kodu źródłowego najczęściej umieszcza się jedno wyrażenie w jednym wierszu. Czasami
jednak zdarzają się sytuacje, kiedy lepiej takie wyrażenie rozciągnąć na wiele linii kodu. W tym celu
używamy:
ukośnika wstecznego \ (ang. backslash), jeżeli wyrażenie nie zawiera nawiasów lub dzielimy je
pomiędzy nimi
nawiasów, jeżeli wyrażenie ich wymaga
In [63]:
a=7*3+\
5 /2
print(a)
23.5
In [65]:
b = [1,2,3,
4,5,6]
print(b)
[1, 2, 3, 4, 5, 6]
In [66]:
c = range(1,
11)
print(c)
range(1, 11)
Znak # oznacza początek komentarza. Tekst pojawiający się po tym znaku aż do końca linii będzie
ignorowany. Wyjątek stanowią komentarze funkcjonalne:
informacja o kodowaniu znaków w kodzie źródłowym, np.:
# -*- coding: utf-8 -*informacja o programie interpretującym kod, np.:
#!/usr/bin/env python
Bardzo ważnym elementem Pythona są wcięcia w kodzie ­ nie tylko zwiększają czytelność całego programu,
ale definiują zawartość bloków kodu.
In [67]:
#pętla po liczbach od 1 do 99
for i in range(1,100):
#jeśli reszta z dzielenia równa 0:
if i%3 ==0:
#wyświetl na ekranie
print(i, '/3 =', i/3)
3 /3 = 1.0
6 /3 = 2.0
9 /3 = 3.0
12 /3 = 4.0
15 /3 = 5.0
18 /3 = 6.0
21 /3 = 7.0
24 /3 = 8.0
27 /3 = 9.0
30 /3 = 10.0
33 /3 = 11.0
36 /3 = 12.0
39 /3 = 13.0
42 /3 = 14.0
45 /3 = 15.0
48 /3 = 16.0
51 /3 = 17.0
54 /3 = 18.0
57 /3 = 19.0
60 /3 = 20.0
63 /3 = 21.0
66 /3 = 22.0
69 /3 = 23.0
72 /3 = 24.0
75 /3 = 25.0
78 /3 = 26.0
81 /3 = 27.0
84 /3 = 28.0
87 /3 = 29.0
90 /3 = 30.0
93 /3 = 31.0
96 /3 = 32.0
99 /3 = 33.0
Dla danego bloku głębokość wcięcia musi być stała. Jednak do dobrych praktyk należy używanie zawsze tej
samej głębokości wcięcia. Należy również unikać naprzemiennego używania tabulatorów i spacji do wcięć,
ponieważ to rodzi problemy przy przenoszeniu kodu między różnymi systemami operacyjnymi. Najlepiej jest
używać edytorów, które zamieniają tabulatory na określoną liczbę spacji w "locie".
Download