W ostatniej części artykułu o typach danych opowiemy o podstawowych typach sekwencyjnych jakimi są isty oraz krotki, a także wprowadzimy pojęcie zbioru.

Listy (list) oraz krotki (tuple) stanowią uporządkowane zbiory danych w postaci obiektów, przy czym mogą być to obiekty różnych typów. Odpowiednikiem list w innych językach programowania często jest tablica, przy czym w językach o statycznym typowaniu może ona przechowywać jedynie obiekty jednego, zadeklarowanego typu, lista w Python’ie może przechowywać obiekty różnych typów.

Listy są mutowalnym typem danych , a więc możliwym do modyfikacji po utworzeniu (można dodawać nowe, modyfikować  oraz usuwać istniejące elementy listy). Listę można utworzyć korzystając z nawiasów kwadratowych lub konstruktora list(obiekt_iterowalny). Krotki są z kolei niemutowalne, do  ich tworzenia służą nawiasy okrągłe lub konstruktor tuple(obiekt_iterowalny).

Przykładowo:

>>> a=('jednoelementowa krotka',)
>>> b=’jeszcze jedna jednoelementowa krotka’,
>>> c=['jednoelementowa lista']

Powyższy przykład tworzy jednoelementowe krotki „a”,”b” oraz listę „c”. Należy zwrócić uwagę, na znak przecinka na końcu jednoelementowych krotek:  bez niego utworzone zostałyby łańcuchy znakowe, a nie krotki!Ponieważ krotki oraz listy są uporządkowanymi zbiorami elementów więc można posługiwać się indeksami w celu wybrania odpowiedniego elementu (należy pamiętać iż indeksy zaczynają się od zera) oraz notacją „plastrową”, np.:

>>> a=["Chapman","Cleese","Terry","Eric","Terry","Michael"]
>>> a[0]
'Chapman'
>>> a[-1]
'Michael'
>>> a[1:3]
['Cleese', 'Terry']
>>> a[0:-1]
['Chapman', 'Cleese', 'Terry', 'Eric', 'Terry']
>>> a[2:]
['Terry', 'Eric', 'Terry', 'Michael']
>>> a[:2]
['Chapman', 'Cleese']

Korzystając z ujemnych indeksów można odwoływać się do elementów od końca. Notacja a[:2] zwraca listę stworzoną z dwóch pierwszych elementów listy „a”, z kolei a[3:] utworzy i zwróci listę złożoną z elementów listy „a” od indeksu 3 do końca.

Charakterystyczna jest własność pakowania/rozpakowania krotek:

>>> x=”Graham”,”John”,”Terry”
>>> x
(”Graham”,”John”,”Terry”)
>>> a,b,c=x
>>> a
”Graham”
>>> b
”John”
>>> c
”Terry”

Poprzez pakowanie utworzona została krotka „x”, która następnie została rozpakowana w ten sposób, iż kolejne jej  wartości zostały przypisane zmiennym „a”, „b” oraz „c”. Rozpakować w ten sposób można także odpowiednią listę. Przy rozpakowywaniu ilość zmiennych (po lewej stronie) musi być równa ilości elementów danej sekwencji (po prawej).

Listę można utworzyć także na podstawie dowolnego, iterowalnego obiektu:

>>> a=[1,2,3,4]
>>> [i**2 for i in a]
[1, 4, 9, 16]

Jest to tak zwana lista składana.

Przy tak tworzonej liście możliwe jest umieszczenie dodatkowej instrukcji warunkowej:

>>> a=(3,4,2,5,7,12)
>>> [i for i in a if i%2==0]
[4, 2, 12]

Powyższe polecenie utworzy listę z parzystych elementów krotki „a”.

Krotki oraz listy posiadają jedynie dwie wspólne metody:

Metoda Opis
zbior.index(element) Zwraca indeks obiektu element w zbiorze zbior. Wyrzuca wyjątek jeśli zbiór nie posiada takiego elementu.
zbior.count(element) Zwraca ilość wystąpień obiektu element w zbiorze zbior.

Lista posiada szereg charakterystycznych dla typu mutowalnego metod:

Metoda Opis
lista.append(element) Dopisuje element do lista.
lista.extend(inna) Dopisuje elementy do lista.
lista.insert(indeks, element) Wstawia do lista obiekt element na pozycji indeks. Elementy listy zostaną przeindeksowane.
lista.remove(x) Usuwa element z lista. Wyrzuca wyjątek jeśli lista nie posiada takiego elementu.
lista.pop([indeks]) Usuwa i zwraca element z listy o podanym indeksie. Jeśli nie podano indeksu usuwa i zwraca ostatni element.
lista.sort() Sortuje listę.
lista.reverse() Odwraca listę.

Dodatkowo, wbudowana funkcja sorted(s) umożliwia utworzenie posortowanej listy z elementów sekwencji „s”.

Jeszcze kilka przykładów użycia list:

a=[‘pierwsza’,’druga’,’trzecia’,123,456,7.0,True]
print a,type(a)
print a[1],type(a[1])
print a[2:4],type(a[2:4])
print a[1][3],type(a[1][3])
print a[1][2:5],type(a[1][2:5])
print a[-3]
print len(a)

w odpowiedzi dostajemy:

print a,type(a)
['pierwsza', 'druga', 'trzecia', 123, 456, 7.0, True]
print a[1],type(a[1])
druga
print a[2:4],type(a[2:4])
['trzecia', 123]
print a[1][3],type(a[1][3])
g
print a[1][2:5],type(a[1][2:5])
uga
print a[-3]
456
print len(a)
7

Python jest językiem bardzo intuicyjnym, z reguły robi to co chcemy:

  1. print a : to oczywiście wypisanie zawartości całej tablicy, tablica „a jest typu list.
  2. print a[1] : wypisujemy drugi element tablicy (numeracja od zera!), którym jest łańcuch „druga”.
  3. print a[2:4] : tu już robi się ciekawiej, wyrażenie a[M,N] tworzy i zwraca nową listę zawierającą elementy z listy „a” od indeksu M do N-1 (a więc w tym przypadku od 2 do 3).
  4. print a[1][3] : do poszczególnych elementów łańcucha (jego liter) mamy dostęp dokładnie w ten sam sposób jak do elementów listy. Wyrażenie a[1] zwraca referencje do drugiego elementu listy „a” (a więc łańcucha ‘druga’), natomiast a[1][3] do czwartegjego elementu – licząc oczywiście od 0 – a tym samym do czwartego znaku czyli litery ‘g’ (zwracany jest 1-elementowy łańcuch).
  5. print a[1][2:5] : analogicznie do dwóch poprzednich przykładów wyrażenie to tworzy nowy łańcuch powstały poprzez wycięcie z łańcucha a[1] liter od 2 do 5-1.
  6. 6. print a[-2] : poprzez użycie znaku minus mamy możliwość dostępu do elementów listy poczynając od jej końca. Ta sama zasada dotyczy również łańcuchów znakowych.
  7. Możemy użyć funkcji len by dowiedzieć się ile elementów liczy lista.

Pisząc dalej w konsoli:

dir([])

Dowiemy się o wszystkich metodach listy:

['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__str__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

Bardziej szczegółowy opis listy oraz każdej z jej metod można wywołać korzystając funkcji pomocy:

help([])
help([].sort)

Duża ilość metod ze znakami “__” odnosi się do operatorów, przykładowo metoda “__add__” odpowiada za przeładowanie operatora “+”: listy można więc do siebie dodawać. Przykładowo pisząc:

x1=[1,2,3,4]
x2=[5,'znaki',False]
x3=x1+x2
print x3
[1, 2, 3, 4, 5, 'znaki', False]

Wyrażenie „x1+x2” tworzy nową listę, będącą złożeniem x1 i x2.

Zbiory

Zbiór – set – jest nieuporządkowaną kolekcją unikalnych obiektów (w przeciwieństwie do list czy krotek dany element może występować tylko raz w zbiorze). Istnieją zbiory mutowalne, tworzone za pomocą polecenia set oraz niemutowalne tworzone poleceniem frozenset. Zbiór można utworzyć na podstawie dowolnego iterowalnego obiektu, np.:

>>> a=['pierwszy',2,3.1415]
>>> s=set(a)
>>> s
{'pierwszy', 2, 3.1415000000000002}
>>> f=frozenset(a)
>>> f
frozenset({'pierwszy', 2, 3.1415000000000002})

Python 3.0 daje także możliwość użycia nawiasów klamrowych do utworzenia obiektu typu set:

>>> a={1,2,3}
>>> a
{1, 2, 3}
>>> type(a)
<class 'set'>

Możliwe jest także utworzenie zbioru składanego (analogicznie do składanych list):

>>> a=('x','y','z')
>>> q={i for i in a}
>>> q
{'y', 'x', 'z'}
>>> type(q)
<class 'set'>

Wprowadzać nowe elementy do zbioru typu set można za pomocą metodą add, a usuwać  metodą discard:

>>> s.add('nowy')
>>> s
{'pierwszy', 2, 3.1415000000000002, 'nowy'}
>>> s.discard(2)
>>> s
{'pierwszy', 3.1415000000000002, 'nowy'}

Do usuwania elementów ze zbioru służy także metoda remove, która wyrzuci wyjątek KeyError przy próbie usunięcia elementu, którego nie ma w zbiorze.

Ponieważ zbiór jest nieuporządkowaną kolekcją obiektów tak więc nie wspiera indeksowania ani notacji „plastrowej” .

Zarówno na zbiorach set oraz frozenset można wykonywać szereg operacji za pomocą zdefiniowanych operatorów lub odpowiednich metod:

Operator/metoda Opis
len(s) Zwraca ilość elementów zbioru s
x in s Prawda jeśli x jest elementem s, w przeciwnym razie Fałsz
s. isdisjoint(o) Prawda jeśli s nie ma elementów wspólnych z o, w przeciwnym razie Fałsz
s.issubset(o)

s < o

Prawda jeśli o jest podzbiorem s
s <= o Prawda jeśli  x<o oraz x!=o
s.issuperset(o)

s > o

Prawda jeśli s jest podzbiorem o
s >= o Prawda jeśli s>o oraz s!=o
s.union(o,…)

s | o | …

Zwraca zbiór będący sumą zbiorów s, o (i kolejnych)
s.intersection(o,…)

s  – o – …

Zwraca zbiór elementów s pomniejszony o elementy zbioru o (i kolejnych)
s.symmetric_difference(o,…)

s ^ o ^ …

Zwraca zbiór elementów będący różnicą symetryczną s, o (i kolejnych)
s.copy() Zwraca zbiór będący tzw. płytką kopią zbioru s.

Powyższe operatory wymagają aby ich argumenty były zbiorami, w przeciwieństwie do metod, którym można przekazać dowolny iterowalny obiekt:

>>> x=set('abcd')>>> y=set('12ac')
>>> x | y
{'a', 'c', 'b', 'd', '1', '2'}
>>> x - y
{'b', 'd'}
>>> x ^ y
{'b', 'd', '1', '2'}
>>> x.union('AB')
{'a', 'A', 'c', 'b', 'd', 'B'}
>>> x.intersection('bc')
{'c', 'b'}
>>> x.symmetric_difference('abc')
{'d'}
Można porównywać i łączyć ze sobą, za pomocą operatorów, zbiory set oraz frozenset :>>> set('ABC')==frozenset('BCA')
True
>>> frozenset('WXY')|set('XYZ')
frozenset({'W', 'Y', 'X', 'Z'})
Operacje, które łączą instancje typu set z frozenset zwracają typ pierwszego operandu.

Typ set jest mutowalny i dlatego też posiada dodatkowo specyficzne operatory i metody umożliwiające różnego rodzaju operacje na zbiorze:

Operator/metoda Opis
s.update(o,…)

s |= o |= …

Aktualizuje zbiór s poprzez wprowadzenie elementów ze zbioru o (i kolejnych jeśli występują) do s
s.intersection_update(o,…)

s &= o &= …

Aktualizuje zbiór s pozostawiając elementy wspólne dla s oraz o (i kolejnych jeśli występują)
s.difference_update(o,…)

s -= o -= …

Aktualizuje zbiór s usuwając elementy znalezione w o (i kolejnych jeśli występują)
s.symmetric_difference_update(o)

s ^= o

Aktualizuje zbiór s pozostawiając elementy niewspólne dla s i o (różnica symetryczna)
s.add(e) Dodaje element e do zbioru s
s.remove(e) Usuwa element e ze zbioru s, wyrzuca wyjątek KeyError jeśli elementu e nie ma w s.
s.discard(e) Usuwa element e ze zbioru s (jeśli istnieje)
s.pop() Usuwa i zwraca element ze zbioru s, wyrzuca wyjątek KeyError jeśli elementu e nie ma w s.
clear() Usuwa wszystkie elementy ze zbioru s

Tu także metodom można przekazać iterowalny argument, operatory mogą działać jedynie na obiektach typu set.

Słowniki

Słowniki zwane również tablicami asocjacyjnymi lub mapami są typem danych w postaci nieuporządkowanych par klucz-wartość.Przy listach oraz krotkach kluczem jest liczba całkowita, natomiast kluczem słownika może być dowolny niezmienny (immutable), a więc haszowalny (hashable) obiekt.

Ponieważ klucze słownika służą do jednoznacznego wskazania określonego obiektu/wartości, więc muszą być (w obrębie danego słownika) unikalne, w przeciwieństwie do obiektów na jakie wskazują (różne klucze w słowniku mogą wskazywać na ten sam obiekt lub różne obiekty tego samego typu, o takich samych wartościach).

Poniższy przykład tworzy 2-elementowy słownik z kluczami różnych typów, wypisuje go wraz z ilością elementów:

>>> s = {1:'ONE','drugi':2.0}
>>> s
{1: 'ONE', 'drugi': 2.0}
>>> s['PI']=3.1415
>>> s
{1: 'ONE', 'drugi': 2.0, 'PI': 3.1415000000000002}
>>> del(s[1])
>>> s
{'drugi': 2.0, 'PI': 3.1415000000000002}

Tak jak i inne typy tak słowniki posiadają szereg charakterystycznych dla nich metod:

Operacja Opis
len(d) Zwraca ilość elementów słownika d
d[key] Zwraca element  słownika d wskazywanym przez klucz key, wyrzuca wyjątek KeyError jeśli takiego klucza nie ma w słowniku.
d[key]=value Przypisuje wartość value do klucza key słownika d.
del d[key] Usuwa element wskazywany przez klucz key ze słownika d, wyrzuca wyjątek KeyError jeśli takiego klucza nie ma w słowniku.
key in d Zwraca True jeśli słownik d posiada klucz key, w przeciwnym razie False.
key not in d Zwraca True jeśli słownik d nie posiada klucza key, w przeciwnym razie False.
clear() Usuwa wszystkie elementy ze słownika.
copy() Tworzy tzw. płytką kopię słownika
fromkeys(seq[, value]) Tworzy i zwraca nowy słownik z kluczami z sekwencji seq, ustawiając ich wartości na value (lub None jeśli nie podano).
d.get(key[, default]) Zwraca element  słownika d o kluczu key jeśli taki istnieje, w przeciwnym razie wartość default (domyślnie None)
d.pop(key[, default]) Usuwa i zwraca element wskazywany przez klucz key słownika d, wyrzuca wyjątek KeyError jeśli takiego klucza nie ma w słowniku.
d.popitem() Usuwa i zwraca krotkę (klucz, wartość) ze słownika d. Jeśli słownik jest pusty wyrzuca wyjątek KeyError.
d.setdefault(key[, default]) Jeśli klucz key jest w słowniku d zwraca jego wartość. Jeśli nie do słownika zostaje wstawiony klucz key o wartości default, która zostanie zwrócona (domyślnie default = None)
d.update([other]) Aktualizuje słownik d kluczami/wartościami z Rother, nadpisując istniejące klucze. Parametr other może być słownikiem jak i dowolnym iterowalnym obiektem zwracającym pary klucz,wartość.

Powyższe metody są wspólne dla Python’a 3.0 oraz 2.6. Ten ostatni posiadał jeszcze (dla zgodności z gałęzią 2) metody iterkeys, itervalues oraz iteritems które zwracały obiekty iterowalne, dzięki którym można było poruszać się odpowiednio po kluczach, wartościach oraz parach klucz/wartość słownika. Te metody nie są już obecne w Python’ie 3.0. Istnieją natomiast metody keys, values oraz items o analogicznym przeznaczeniu (metody te także są obecne w Python’ie 2.6, lecz zwracają tam listy zamiast iterowalnych obiektów).

Poniższy przykład tworzy 2-elementowy słownik z kluczami różnych typów, wypisuje go wraz z ilością elementów. Polecenie dir zwraca listę metod słownika.

my_dict = {1:1,'dwa':2.0}
print my_dict ,  len(my_dict)
{1: 1, 'dwa’:2.0}

dir(my_dict)
['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__str__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']

Raz utworzonemu słownikowi można zarówno dodawać, ujmować jak i zastępować elementy:

>>> my_dict['xxx']=123
>>> print my_dict
{1: 1, 'xxx': 123, 'dwa': 2.0}
>>> del(my_dict['xxx'])
>>> print my_dict
{1: 1, 'dwa': 2.0}
>>> print my_dict.keys()
[1, 'dwa']
print my_dict.values()
[1, 2.0]
>>> >>> print my_dict.items()
[(1, 1), ('dwa', 2.0)]

W powyższym przykładzie użyte zostały trzy użyteczne metody słownika:

  • keys : zwraca listę kluczy słownika.
  • values : zwraca listę wartości słownika.
  • items : zwraca listę, której elementami są krotki (klucz,wartość) słownika.

Funkcja dict umożliwia utworzenie słownika z krotki lub listy:

>>> krotka=((1,'jeden'),('2',222))
>>> lista=[['111',1],[2,'dwa']]
>>> dict(krotka)
{1: 'jeden', '2': 222}
>>> dict(lista)
{2: 'dwa', '111': 1}