Po uruchomieniu IDLE'a zgłasza się tryb interaktywny Pythona.
Wykorzystamy go do poznania pythonowskich sekwencyjnych typów danych.
Sekwencyjne typy danych służą do zapamiętywania wielu wartości w pojedynczej zmiennej, w odróżnieniu od typów prostych, takich jak int, które w pojedynczej zmiennej mogą zachować tylko jedną wartość.
Do tej pory poznaliśmy już jeden typ sekwencyjny. Jest nim typ napisowy (string) - patrz punkty 2.13-2.16. Przypomnijmy, że wartości napisów podajemy w cudzysłowach lub apostrofach:
>>> txt="napis"
>>> txt2='napis'
I, że możemy na nich wykonywać pewne operacje, np.:
>>> txt2+='owi nierówny'
>>> print txt2
napisowi nierówny
Napisy są sekwencjami znaków. Każdy typ sekwencyjny pozwala na dostęp do każdego swojego elementu z osobna. Aby uzyskać dostęp do znaku na określonej pozycji podajemy jej indeks (numer porządkowy liczony od lewej, zero oznacza pierwszy znak napisu) w nawiasach kwadratowych bezpośrednio po napisie:
>>> "abc"[0]
'a'
>>> "abc"[1]
'b'
>>> "abc"[2]
'c'
>>>
txt[0]
'n'
>>>
txt[1]
'a'
>>>
txt[2]
'p'
>>>
txt[3]
'i'
>>>
txt[4]
's'
>>>
txt[5]
Traceback
(most recent call last):
File "<pyshell#22>", line 1,
in -toplevel-
txt[5]
IndexError:
string index out of range
>>>
Powodem błędu była próba odczytania znaku o zbyt wysokim numerze, którego w napisie nie ma. Aby poznać długość napisu, posługujemy się funkcją len:
>>>
len("abc")
3
>>>
len(txt)
5
>>> len(txt2)
17
>>> len(txt*20)
100
>>>
Zliczać znaki możemy także od końca napisu w prawo. Używamy w tym celu indeksów ujemnych (-1 oznacza ostatni znak napisu):
>>> "abc"[-1]
'c'
>>> "abc"[-2]
'b'
>>>
"abc"[-3]
'a'
>>>
txt[-1]
's'
>>>
Pojedynczy znak zapisany jest jako liczba odpowiadająca kodowi ASCII określonego symbolu graficznego.
Aby poznać kod ASCII określonego znaku, należy użyć funkcji ord:
>>>
ord('A')
65
>>>
ord('a')
97
>>> ord("1")
49
>>> ord("2")
50
Parametrem funkcji ord musi być pojedynczy znak, a nie wieloznakowy napis:
>>>
ord(txt[0])
110
>>>
ord(txt)
Traceback
(most recent call last):
File "<pyshell#52>", line 1,
in -toplevel-
ord(txt)
TypeError:
ord() expected a character, but string of length 5 found
>>>
Aby zamienić kod ASCII na odpowiadający mu znak, używamy funkcji chr:
>>>
chr(65)
'A'
>>>
chr(32)
'
'
>>>
chr(10)
'\n'
>>>
chr(49)+chr(48)+chr(50)
'102'
>>>
Czasami interesuje nas nie pobranie z napisu pojedynczego znaku, ale wykrojenie ciągu znaków. Do wykrajania fragmentów napisów używamy zapisu z dwukropkiem:
Fragment napisu do ósmego znaku:
>>> txt2[:8]
'napisowi'
Fragment napisu od dziesiątego znaku:
>>> print txt2[9:]
nierówny
Fragment napisu od szóstego do dwunastego znaku:
>>> txt2[5:12]
'owi nie'
Co drugi znak z fragmentu napisu od szóstego do dwunastego znaku:
>>> txt2[5:12:2]
'oine'
Możemy także używać indeksów ujemnych:
>>> txt2[:-9]
'napisowi'
>>> txt2[-8:]
'nier\xf3wny'
>>> txt2[-12:-5]
'owi nie'
>>> txt2[-12:-5:2]
'oine'
Sekwencyjne typy danych w Pythonie dzielimy na zmienne (mutable) i niezmienne (immutable). Typ napisowy należy do typów niezmiennych.
Typy niezmienne nie mogą zmieniać swojej wartości. A zatem zapis:
>>>
txt+=chr(32)+txt2
>>>
print txt
napis napisowi nierówny
tak naprawdę nie zmienia wartości zmiennej txt, ale tworzy nową zmienną o tej samej nazwie, a innej wartości, starą usuwając.
Konsekwencją niezmienności typu napisowego jest niemożność zmiany jego elementu:
>>>
txt[2]='w'
Traceback
(most recent call last):
File "<pyshell#41>", line 1,
in -toplevel-
txt[2]='w'
TypeError:
object does not support item assignment
>>>
ani fragmentu:
>>> txt[2:4]='wis'
Traceback
(most recent call last):
File "<pyshell#93>", line 1,
in -toplevel-
txt[2:4]='wis'
TypeError:
object doesn't support slice assignment
>>>
Oczywiście, pożądaną operację możemy wykonać, inaczej formułując polecenie:
>>>
txt2=txt[:2]+"w"+txt[3:]
>>> print txt2
nawis napisowi nierówny
>>>
Napisy mogą przechowywać sekwencje znaków. Czasami potrzebujemy jednak zapamiętać sekwencje danych nie będących znakami, ale np. liczbami lub innymi sekwencjami.
Do przechowywania takich sekwencji służą w Pythonie: krotki (tuples) i listy (lists).
Elementy zarówno krotek, jak i list mogą być dowolnego typu.
Krotki są typem niezmiennym. Oznacza to, że mają z góry ustaloną długość, a zmiana wartości poszczególnych elementów z osobna nie jest możliwa.
Listy są typem zmiennym. Oznacza to, że można je łatwo skracać i wydłużać i jest możliwa zmiana wartości poszczególnych elementów z osobna.
Listy tworzymy używając nawiasów kwadratowych, rozdzielając ich elementy przecinkami.
Aby stworzyć listę trzech liczb naturalnych, napiszemy:
>>> lista1 = [1, 2, 3]
>>> lista1
[1, 2, 3]
Aby stworzyć listę złożoną z czterech napisów, napiszemy:
>>> lista2 =
["pierwszy", txt, txt2, "ostatni"]
>>> lista2
['pierwszy', 'napis napisowi
nier\xf3wny', 'nawis napisowi nier\xf3wny', 'ostatni']
Listy mogą zawierać elementy różnych typów:
>>> lista3 = [1.0, 2,
"trzy"]
>>> lista3
[1.0, 2, 'trzy']
Listy mogą zawierać inne listy:
>>> lista4=[ [1, 2, 3],
["Nocny", "Dzienny"] ]
>>> lista4
[[1, 2, 3], ['Nocny', 'Dzienny']]
Listy mogą być puste:
>>> lista_pusta = []
>>> lista_pusta
[]
>>> len(lista_pusta)
0
Listy mogą zawierać tylko jeden element:
>>> lista_jednoelementowa =
[1]
>>> lista_jednoelementowa
[1]
Można odczytywać wybiórczo zawartość poszczególnych elementów listy:
>>> lista1[0]
1
>>> lista2[-1]
'ostatni'
Lub ich ciągów:
>>> lista1[1:]
[2, 3]
>>> lista2[0::3] # co trzeci
element listy
['pierwszy', 'ostatni']
>>> lista4[1:]
[['Nocny', 'Dzienny']]
Listy można powielać:
>>> lista2*=2
>>> lista2
['pierwszy', 'napis napisowi
nier\xf3wny', 'nawis napisowi nier\xf3wny', 'ostatni', 'pierwszy', 'napis
napisowi nier\xf3wny', 'nawis napisowi nier\xf3wny', 'ostatni']
>>> []*1000
[]
>>> [1,2,3]*0
[]
Określać ich długość:
>>> len(lista2)
8
Skracać:
>>> lista2=lista2[:3]
>>> lista2
['pierwszy', 'napis napisowi
nier\xf3wny', 'nawis napisowi nier\xf3wny']
Wydłużać:
>>> lista2+=['ostatni']
>>> lista2
['pierwszy', 'napis napisowi
nier\xf3wny', 'nawis napisowi nier\xf3wny', 'ostatni']
Listy są sekwencjami zmiennymi, można więc modyfikować ich fragmenty:
>>> lista3
[1.0, 2, 'trzy']
>>>
lista3[0:2]=["jeden","dwa"]
>>> lista3
['jeden', 'dwa', 'trzy']
lub pojedyncze elementy:
>>> lista1
[1, 2, 3, 4]
>>> lista1[2]+=1
>>> lista1
[1, 2, 4, 4]
Można też usuwać elementy ze środka listy, tak samo jak w sekwencjach niezmiennych:
>>>
lista2=lista2[:2]+lista2[3:]
>>> lista2
['pierwszy', 'napis napisowi
nier\xf3wny', 'ostatni']
Lub prościej, z użyciem instrukcji del, np.:
>>> del lista2[1]
>>> lista2
['pierwszy', 'ostatni']
Porównywanie list odbywa się na zasadzie porównywania poszczególnych elementów:
- jeżeli elementy obu list są sobie równe, listy są równe
- jeżeli listy różnią się choć jednym elementem, to są nierówne
- jeżeli pierwszy element pierwszej listy jest większy od pierwszego elementu drugiej listy, to pierwsza lista jest większa od drugiej
- jeżeli pierwszy element pierwszej listy jest taki sam jak pierwszy element drugiej listy, decyduje porównanie drugich elementów, itd.
- element nieistniejący jest zawsze mniejszy od każdego innego elementu
>>> lista1 == [1, 2, 4, 4]
True
>>> lista1 != [1, 2, 3, 4]
True
>>> lista1 > [1, 2, 2, 5]
True
>>> lista1 < [1, 2, 4, 4,
5]
True
Aby sprawdzić, czy określona wartość znajduje się na liście, używamy operatora in:
>>>
1 in lista1
True
>>>
2 not in lista1
False
>>> "pierwszy" in
lista2
True
W przypadku list wielopoziomowych, to jest takich, które zawierają inne listy, np.:
>>> lista4
[[1, 2, 3], ['Nocny', 'Dzienny']]
możliwy jest dostęp do poszczególnych elementów list podrzędnych poprzez użycie dwóch indeksów:
>>> lista4[1][0]
'Nocny'
>>> lista4[0][1]
2
Jako pierwszy podajemy zawsze indeks listy wyższego rzędu.
W Pythonie wszystkie sekwencje zmienne nie odnoszą się do określonych danych, ale do miejsca w pamięci, w którym te dane się znajdują.
W związku z tym przypisanie listy do listy nie kopiuje wartości, a jedynie wskaźnik do nich:
>>> lista5=lista1
>>> lista5
[1, 2, 4, 4]
A zatem od tej pory, niezależnie czy zmieniamy elementy listy 1 czy 5, zmieniamy obie, bo zmianie tak naprawdę podlegają te same dane:
>>> lista1[2]=3
>>> lista5
[1, 2, 3, 4]
>>> lista5[2]=5
>>> lista1
[1, 2, 5, 4]
Jeżeli listę utworzono z innych list:
>>> lista6=[0,lista1]
>>> lista6
[0, [1, 2, 5, 4]]
To każda zmiana ich wartości będzie przenoszona na listę nadrzędną:
>>> lista1[1]=4
>>> lista6
[0, [1, 4, 5, 4]]
Co więcej, zmiana wartości listy nadrzędnej będzie przenoszona na listę podrzędną:
>>> lista6[1][0]=2
>>> lista1
[2, 4, 5, 4]
Krotki pod wieloma względami przypominają listy, w podobny sposób tworzymy je i sprawdzamy ich wartości. W odróżnieniu od list, krotki są sekwencjami niezmiennymi, co powoduje różnice w sposobie ich modyfikacji.
Krotki tworzymy używając nawiasów okrągłych, rozdzielając ich elementy przecinkami.
Aby stworzyć krotkę z trzech liczb naturalnych, napiszemy:
>>> krotka1=(1,2,3)
>>> krotka1
(1, 2, 3)
Przy czym nawiasy okrągłe można pomijać:
>>> krotka1=1,2,3
>>> krotka1
(1, 2, 3)
(Dla zachowania przejrzystości my tego robić nie będziemy.)
Krotki mogą zawierać elementy różnych typów:
>>> krotka2=(1.0, 2,
"trzy")
>>> krotka2
(1.0, 2, 'trzy')
W tym sekwencyjnych
>>> krotka3=(krotka1, lista1)
>>> krotka3
((1, 2, 3), [2, 4, 5, 4])
Krotki mogą być puste:
>>> krotka_pusta = ()
>>> krotka_pusta
()
>>> len (krotka_pusta)
0
Krotki mogą zawierać tylko jeden element. Jako że zapis (1) oznacza liczbę jeden w nawiasie, tworząc krotki jednoelementowe obowiązkowo na ich końcu stawiamy przecinek:
>>> liczba=(1)
>>> liczba
1
>>>
krotka_jednoelementowa=(1,)
>>> krotka_jednoelementowa
(1,)
>>>
len(krotka_jednoelementowa)
1
>>>
Można odczytywać wybiórczo zawartość poszczególnych elementów krotki:
>>> krotka1[1]
2
>>> krotka3[-1]
[2, 4, 5, 4]
Lub ich ciągów:
>>> krotka1[1:]
(2, 3)
>>> krotka1[::2] # co drugi
element krotki
(1, 3)
Krotki można powielać:
>>> krotka1*=2
>>> krotka1
(1, 2, 3, 1, 2, 3)
Skracać:
>>> krotka1=krotka1[:3]
>>> krotka1
(1, 2, 3)
Wydłużać:
>>> krotka1=krotka1+(4,)
>>> krotka1
(1, 2, 3, 4)
Krotki są sekwencjami niezmiennymi, więc nie można modyfikować ich fragmentów:
>>>
krotka1[2]=1
Traceback
(most recent call last):
File "<pyshell#151>", line
1, in -toplevel-
krotka1[2]=1
TypeError:
object does not support item assignment
Oczywiście, pożądaną operację możemy wykonać, inaczej formułując polecenie:
>>> krotka1=krotka1[:2]+(1,)+krotka1[3:]
>>> krotka1
(1, 2, 1, 4)
Krotki są sekwencjami niezmiennymi, w związku z tym przypisanie krotki do krotki kopiuje faktyczne wartości, a nie jedynie wskaźnik do nich:
>>> krotka4=krotka1
>>> krotka4
(1, 2, 1, 4)
>>> krotka1=(1,2,3,4)
>>> krotka4
(1, 2, 1, 4)
W konwersji typów sekwencyjnych używamy następujących instrukcji:
- list zamienia typ sekwencyjny na listę
>>> lista7=list(krotka5)
>>> lista7
[2, 4, 5, 4]
>>>
lista8=list("abcd")
>>> lista8
['a', 'b', 'c', 'd']
- tuple zamienia typ sekwencyjny na krotkę
>>> krotka5=tuple(lista1)
>>> krotka5
(2, 4, 5, 4)
>>>
krotka6=tuple("abcd")
>>> krotka6
('a', 'b', 'c', 'd')
- str zamienia typ sekwencyjny na napis
>>> str(krotka6)
"('a', 'b', 'c', 'd')"
>>> str(lista7)
'[2, 4, 5, 4]'
Lub krócej, przy użyciu odwróconych apostrofów:
>>> `krotka6`
"('a', 'b', 'c', 'd')"
>>> `lista7`
'[2, 4, 5, 4]'
Aby wykonać jakieś operacje na wszystkich lub wybranych elementach sekwencji, najprościej jest posłużyć się pętlą for ... in.
Przykładowo, aby wyświetlić w kolejnych liniach wszystkie elementy sekwencji lista1 napiszemy:
>>>
for a in lista1:
print
a
2
4
5
4
gdzie a jest przykładową zmienną, która w danym powtórzeniu pętli przyjmuje wartość kolejnych elementów sekwencji.
Aby poznać numer aktualnego powtórzenia pętli, posługujemy się funkcją enumerate:
>>>
for nr, wartosc in enumerate(lista2):
print
nr,
print
wartosc
0 pierwszy
1 ostatni
gdzie nr jest zmienną zawierająca aktualny numer obiegu pętli, a wartosc zmienną, która w danym powtórzeniu pętli przyjmuje wartość kolejnych elementów sekwencji.
Możemy wykonywać pętlę tylko dla fragmentu sekwencji:
>>>
for i in lista7[1:3]:
print i,i**2
4 16
5 25
A wewnątrz pętli wykonywać instrukcje warunkowe:
>>>
for i in lista7:
if i>0:
print i, i**0.5
2 1.41421356237
4 2.0
5 2.2360679775
4 2.0
I. Napisz program "parzyste2.py", który wczyta od użytkownika liczbę całkowitą i bez użycia instrukcji if wyświetli informację, czy jest to liczba parzysta, czy nieparzysta.
II. Napisz program "numer.py", który zamieni wprowadzony przez użytkownika ciąg cyfr na formę tekstową:
a. znaki nie będące cyframi mają być ignorowane
b. konwertujemy cyfry, nie liczby, a zatem:
i. 911 to "dziewięć jeden jeden"
ii. 1100 to "jeden jeden zero zero"