In [4]:
%%javascript
$.getScript('http://kmahelona.github.io/ipython_notebook_goodies/ipython_notebook_toc.js')

Złożone typy danych (kolekcje)

Podstawowe typy złożone (kolekcje) to krotki, listy, zbiory i slowniki. Dwa pierwsze typy przechowuja elementy w sposob uporzadkowany - kazdemu elementowi przypisany jest unikalny indeks $i \in \{0,\ldots,n-1\}$ gdzie $n \in \mathbb{N}$ jest liczebnością kolekcji (dlatego alternatywnie typy te sa nazywane ciągami lub sekwencjami). Pozwala to na dostep do wskazanych elementow jak do elementow tablicy. Zbiory i slowniki nie przechowuja elementow w okreslonej kolejnosci, ale gwarantuja unikalnosc elementow.

krotki (tuple)

Najprostszym złożonym typem danych w Pythonie sa krotki czyli n-tki uporządkowane. Krotki przechowują uporządkowane ciągi elementów dowolnego typu. Elementy nie muszą być unikalne.

In [4]:
n = (1,2,4,4, 5.,'Ala',(1,3))
n
Out[4]:
(1, 2, 4, 4, 5.0, 'Ala', (1, 3))
In [5]:
type(n)
Out[5]:
tuple
In [9]:
type(n[-1])
Out[9]:
tuple

mozemy pominac nawiasy kiedy typ danych wynika jasno z kontekstu:

In [11]:
n=1,2,5,4
n
Out[11]:
(1, 2, 5, 4)
In [12]:
type(n)
Out[12]:
tuple

ale w przypadkach niejednoznacznych trzeba uzywac nawiasow

In [13]:
type(1,2,5,4) # błąd!
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-13-2b0cfc155dc6> in <module>()
----> 1 type(1,2,5,4) # błąd!

TypeError: type() takes 1 or 3 arguments
In [18]:
type((1,2,5,4,))
Out[18]:
tuple

aby utworzyc krotke jednoelementowa uzywamy składni:

In [21]:
type((1.,))
Out[21]:
tuple

lub

In [19]:
1.,
Out[19]:
(1.0,)

podobnie jak ciągi znaków krotki mozna konkatenowac

In [23]:
(1,2,5,4) + ('a',3.) + (3,)
Out[23]:
(1, 2, 5, 4, 'a', 3.0, 3)
In [24]:
# oraz powielac
n=(1,2,5,4)*3
n
Out[24]:
(1, 2, 5, 4, 1, 2, 5, 4, 1, 2, 5, 4)
In [25]:
# ale nie mozna modyfikowac elementow krotki po jej utworzeniu
n[1]=3
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-25-ae94169618c3> in <module>()
      1 # ale nie mozna modyfikowac elementow krotki po jej utworzeniu
----> 2 n[1]=3

TypeError: 'tuple' object does not support item assignment
In [30]:
help(tuple)
Help on class tuple in module builtins:

class tuple(object)
 |  tuple() -> empty tuple
 |  tuple(iterable) -> tuple initialized from iterable's items
 |  
 |  If the argument is a tuple, the return value is the same object.
 |  
 |  Methods defined here:
 |  
 |  __add__(self, value, /)
 |      Return self+value.
 |  
 |  __contains__(self, key, /)
 |      Return key in self.
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(self, key, /)
 |      Return self[key].
 |  
 |  __getnewargs__(...)
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __hash__(self, /)
 |      Return hash(self).
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __mul__(self, value, /)
 |      Return self*value.n
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __rmul__(self, value, /)
 |      Return self*value.
 |  
 |  count(...)
 |      T.count(value) -> integer -- return number of occurrences of value
 |  
 |  index(...)
 |      T.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.

In [28]:
n
Out[28]:
(1, 2, 5, 4, 1, 2, 5, 4, 1, 2, 5, 4)
In [31]:
n.index(5)
Out[31]:
2
In [32]:
n.count(5)
Out[32]:
3

Krotki sa prostszym typem danych niz lista i oferuja tylko dwie metody:

In [ ]:
help(tuple.count)
help(tuple.index)

listy (lists)

Pdobnie jak krotki, listy przechowywuja uporządkowane ciągi elementów dowolnego typu. Listę tworzymy uzywająć nawiasow kwadratowych. Listy moga zawierac powtarzajace sie elementy.

In [33]:
[1,2,4,4]
Out[33]:
[1, 2, 4, 4]

Listy mozna tworzyc w kilku liniach. Moga zawierac elementy roznych typow

In [34]:
n = [ 1,
3.4,
'hello',
True,
2-1J, (1,2,3)]
In [35]:
n
Out[35]:
[1, 3.4, 'hello', True, (2-1j), (1, 2, 3)]

Listy indeksujemy podobnie jak ciagi znakow. 1-szy element ma indeks 0

In [36]:
n[1]
Out[36]:
3.4

element ostatni ma indeks -1

In [37]:
n[2:-1]
Out[37]:
['hello', True, (2-1j)]

dla elementów 'zagniezdzonych' mozemy uzywac notacji jak dla tablic wielowymiarowych:

In [43]:
n = [1, 3.4, 'hello', True, (2-1j), [1, 2, 3]]
In [44]:
n
Out[44]:
[1, 3.4, 'hello', True, (2-1j), [1, 2, 3]]
In [45]:
n[-1][1] = 5
In [46]:
n
Out[46]:
[1, 3.4, 'hello', True, (2-1j), [1, 5, 3]]

podobie jak ciagi znakow listy mozna konkatenowac

In [47]:
n + [3, 4, 'pięć']
Out[47]:
[1, 3.4, 'hello', True, (2-1j), [1, 5, 3], 3, 4, 'pięć']

oraz powielać

In [67]:
n = [1,2,3,5] * 2
n
Out[67]:
[1, 2, 3, 5, 1, 2, 3, 5]

w odrożnieniu od krotek zawartosc listy mozemy modyfikowac:

In [64]:
n = [1,2,3,'blah']
n
Out[64]:
[1, 2, 3, 'blah']
In [52]:
n[3]=4
n
Out[52]:
[1, 2, 3, 4, 'Ala']
In [54]:
n.append('Ala')
In [63]:
n
Out[63]:
(5, 5, 3, 4)
In [56]:
n = 5,
n
Out[56]:
(5,)
In [57]:
n += 5,3,4
n
Out[57]:
(5, 5, 3, 4)
In [58]:
n += [0]
n
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-58-f5efb7ac93f6> in <module>()
----> 1 n += [0]
      2 n

TypeError: can only concatenate tuple (not "list") to tuple
In [ ]:
n[n.index('Ala')]=1.354
In [68]:
n
Out[68]:
[1, 2, 3, 5, 1, 2, 3, 5]

listy mozna sortowac w porzadku rosnacym

In [69]:
n.sort()
n
Out[69]:
[1, 1, 2, 2, 3, 3, 5, 5]

lub malejacym

In [70]:
n.sort(reverse=True)
n
Out[70]:
[5, 5, 3, 3, 2, 2, 1, 1]

mozna tez odwrocic kolejnosc elementow

In [71]:
n
Out[71]:
[5, 5, 3, 3, 2, 2, 1, 1]
In [77]:
n.reverse()
n
Out[77]:
[5, 5, 3, 3, 2, 2, 1, 1]
In [78]:
help(list)
Help on class list in module builtins:

class list(object)
 |  list() -> new empty list
 |  list(iterable) -> new list initialized from iterable's items
 |  
 |  Methods defined here:
 |  
 |  __add__(self, value, /)
 |      Return self+value.
 |  
 |  __contains__(self, key, /)
 |      Return key in self.
 |  
 |  __delitem__(self, key, /)
 |      Delete self[key].
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(...)
 |      x.__getitem__(y) <==> x[y]
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __iadd__(self, value, /)
 |      Implement self+=value.
 |  
 |  __imul__(self, value, /)
 |      Implement self*=value.
 |  
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __mul__(self, value, /)
 |      Return self*value.n
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __reversed__(...)
 |      L.__reversed__() -- return a reverse iterator over the list
 |  
 |  __rmul__(self, value, /)
 |      Return self*value.
 |  
 |  __setitem__(self, key, value, /)
 |      Set self[key] to value.
 |  
 |  __sizeof__(...)
 |      L.__sizeof__() -- size of L in memory, in bytes
 |  
 |  append(...)
 |      L.append(object) -> None -- append object to end
 |  
 |  clear(...)
 |      L.clear() -> None -- remove all items from L
 |  
 |  copy(...)
 |      L.copy() -> list -- a shallow copy of L
 |  
 |  count(...)
 |      L.count(value) -> integer -- return number of occurrences of value
 |  
 |  extend(...)
 |      L.extend(iterable) -> None -- extend list by appending elements from the iterable
 |  
 |  index(...)
 |      L.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |  
 |  insert(...)
 |      L.insert(index, object) -- insert object before index
 |  
 |  pop(...)
 |      L.pop([index]) -> item -- remove and return item at index (default last).
 |      Raises IndexError if list is empty or index is out of range.
 |  
 |  remove(...)
 |      L.remove(value) -> None -- remove first occurrence of value.
 |      Raises ValueError if the value is not present.
 |  
 |  reverse(...)
 |      L.reverse() -- reverse *IN PLACE*
 |  
 |  sort(...)
 |      L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __hash__ = None

mozna sumowac elementy listy

In [85]:
sum(n)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-85-667e68ad4f49> in <module>()
----> 1 sum(n)

TypeError: unsupported operand type(s) for +: 'int' and 'str'

wybierac elementy skrajne

In [86]:
min(n), max(n)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-86-7abccb5aec89> in <module>()
----> 1 min(n), max(n)

TypeError: unorderable types: str() < int()

pod warunkiem ze typy elemetow sa zgodne

In [84]:
n.append('name2')
n
Out[84]:
[5, 5, 3, 3, 2, 2, 1, 1, 'name2']

Listy możemy używać jako kolejek. Do wrzucania elementow na koniec kolejki sluzy metoda 'append':

In [89]:
n = []
n
Out[89]:
[]
In [114]:
n.append(1)
n.append('Ala')
n.append(4.234)
n
Out[114]:
[1, 'Ala', 4.234]

Przykład kolejki LIFO (taka struktura danych jest tez nazywana stosem) -- do pobrania ostatnio wrzuconego elementu uzywamy metody 'pop()':

In [115]:
x = n.pop(0)
print("pobrano:", x, " w kolejce pozostalo", len(n), "elementów:", n)
pobrano: 1  w kolejce pozostalo 2 elementów: ['Ala', 4.234]
In [ ]:
print("pobrano:", x, " w kolejce pozostalo", len(n), "elementów:", n)

Przykład kolejki FIFO -- do pobierania najstarszego wrzuconego elementu uzywamy wywolania 'pop(0)':

In [ ]:
n.append(222)
In [ ]:
n
In [ ]:
x = n.pop(n.index(4.234))
x
In [ ]:
x = n.pop(0)
print("pobrano:", x, " w kolejce pozostalo", len(n), "elementów:", n)
In [ ]:
help(list)

mozemy tworzyc listy z wykorzystaniem generatorow (jak funkcja range()):

In [116]:
list(range(10))
Out[116]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [117]:
n=list(range(1,11))
n
Out[117]:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In [118]:
type(n)
Out[118]:
list

mozemy usuwac elementy listy wskazujac ich indeksy

In [119]:
n
Out[119]:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In [120]:
del(n[2])
n
Out[120]:
[1, 2, 4, 5, 6, 7, 8, 9, 10]

lub wartosci

In [121]:
n.remove(10)
n
Out[121]:
[1, 2, 4, 5, 6, 7, 8, 9]

wycinanie fragmetu listy (slicing):

In [122]:
n[3:5]
Out[122]:
[5, 6]

wstawianie listy dowolnego rozmiaru w srodek innej listy:

In [123]:
n[3:5]=['A','B','C','D']
n
Out[123]:
[1, 2, 4, 'A', 'B', 'C', 'D', 7, 8, 9]

Mozna zadac pytanie po co nam krotki skoro listy oferuja to co krotki i wiele wiecej? Gospodarka pamiecia w przypadku krotek jest znacznie bardziej oszczedna niz w przypadku list. Jesli nie musisz modyfikowac zestawu danych - do jego przechowania uzywaj krotek!

zbiory (sets)

zbiory to proste kolekcje przechowujace elementy dowolnego typu ktorych kolejnosc jest nieistotna

In [124]:
z = {'Ola', 5.2, 'Ala', 'Ela'}
z
Out[124]:
{'Ela', 'Ala', 5.2, 'Ola'}
In [127]:
z[1]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-127-e7abb66cbb1e> in <module>()
----> 1 z[1]

TypeError: 'set' object does not support indexing

elementów zbioru nie mozemy indeksowac poniewaz ich kolejnosc jest nieokreslona:

In [ ]:
z[1]

elementy zbioru mozna usuwac

In [128]:
z.remove(5.2)
z
Out[128]:
{'Ala', 'Ela', 'Ola'}

elementy mozna dodawac

In [129]:
z.add('Ula')
z
Out[129]:
{'Ala', 'Ela', 'Ola', 'Ula'}

elementy zbioru sa unikalne:

In [135]:
z.add('Ala')
z
Out[135]:
{'Ala', 'Ela', 'Ola', 'Ula'}

Python wspiera następujące działania na zbiorach:


Operator Nazwa Wyjaśnienie Przykłady
o
p
e
r
c
j
e

n
a

z
b
i
o
r
a
c
h
| Suma zbiorów Zwraca zbiór wszystkich elementów które są w pierwszym zbiorze lub są w drugim zbiorze. set([1,3,5]) | set([7,3]) daje set([1,3,5,7]).
Różnica zbiorów Zwraca zbiór elementów które są w pierwszym zbiorze i nie są w drugim zbiorze. set([1,3,5]) − set([7,3]) daje set([1,5]).
& Przecięcie (część wspólna, iloczyn) zbiorów Zwraca zbiór elementów które są w pierwszym zbiorze i są w drugim zbiorze. set([1,3,5]) & set([7,3]) daje set([3]).
^ Elementy unikalne Zwraca zbiór zawierający elementy nie będące wspólne dla dwu zbiorów. set([1,3,5]) ^ set([7,3]) daje set([1,5,7]).
in Sprawdzenie czy jest elementem. Zwraca wartość logiczną zdania „x jest elementem zbioru A”. 3 in set([1,3,5]) daje True.
not in Sprawdzenie czy nie jest elementem Zwraca wartość logiczną zdania „x nie jest elementem zbioru A”. 3 not in set([1,3,5]) daje False.
< Sprawdzenie czy jest podzbiorem Zwraca wartość logiczną zdania „A jest podzbiorem zbioru B”. set([1,3]) < set([7,3]) daje False.
set([1,3]) < set([1,7,3]) daje True.
> Sprawdzenie czy jest nadzbiorem Zwraca wartość logiczną zdania „A jest nadzbiorem zbioru B”. set([1,5,3]) > set([7,3]) daje False.
set([1,5,3]) > set([1,3]) daje True.
== Sprawdzenie czy są jednakowe Zwraca wartość logiczną twierdzenia, że każdy element pierwszego zbioru jest elementem drugiego zbioru i każdy element drugiego zbioru jest elementem pierwszego. set([1,3,5]) == set([7,3]) daje False.
set([1,3,5]) == set([5,3,1]) daje True.
 != Sprawdzenie czy nie są jednakowe Zwraca wartość logiczną twierdzenia, że pierwszy zbiór nie jest jednakowy z drugim. set([1,3,5]) != set([7,3]) daje True.

przyklady:

In [136]:
y = {'Ela', 'Ala', 'Ania'}
print('zbior y: ', y, '\nzbior z: ', z)
zbior y:  {'Ela', 'Ala', 'Ania'} 
zbior z:  {'Ela', 'Ala', 'Ula', 'Ola'}
In [137]:
# suma
y | z
Out[137]:
{'Ala', 'Ania', 'Ela', 'Ola', 'Ula'}
In [138]:
# czesc wspolna
y & z
Out[138]:
{'Ala', 'Ela'}
In [139]:
# czy 'Ala' jest elementem zbioru y?
'Ala' in y
Out[139]:
True

słowniki (dict)

Słowniki sa implementacją tzw. tablic asocjacyjnych. Przechowuja one mapowania 'klucz:wartosc'. Klucze sa unikalne. Kluczem moze byc dowolny obiekt niemodyfikowalnego typu danych czyli liczba, string, krotka.

In [8]:
s = {'Sty':1, 'Lut':2, 'Mar':3, 'Kwie':0, 'Maj':5, 'Lip':7, 'Sie':8, 'Wrz':9, 
     'Paz':10, 'Lis':11, 'Gru':12, '???':13}
In [11]:
type(s)
Out[11]:
dict
In [12]:
s
Out[12]:
{'???': 13,
 'Gru': 12,
 'Kwie': 0,
 'Lip': 7,
 'Lis': 11,
 'Lut': 2,
 'Maj': 5,
 'Mar': 3,
 'Paz': 10,
 'Sie': 8,
 'Sty': 1,
 'Wrz': 9}

w przeciwienstwie do uporządkowanych kolekcji danych takich jak krotki i listy elementy słownika nie są uporzadkowanie wiec ze slownika nie mozemy pobierac wartosci przez podanie indeksu elementu:

In [13]:
s[1]
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-13-88de191fe097> in <module>()
----> 1 s[1]

KeyError: 1

ale do elementow slownika mozemy odwolywac sie przez podanie wartosci klucza:

In [14]:
s['Maj']
Out[14]:
5
In [16]:
s.get('Kwie')
Out[16]:
0

wstawianie nowej wartosci do slownika

In [17]:
s['Cze']=6
s
Out[17]:
{'???': 13,
 'Cze': 6,
 'Gru': 12,
 'Kwie': 0,
 'Lip': 7,
 'Lis': 11,
 'Lut': 2,
 'Maj': 5,
 'Mar': 3,
 'Paz': 10,
 'Sie': 8,
 'Sty': 1,
 'Wrz': 9}

zmiana wartosci przypisanej do klucza

In [18]:
s['Kwie']=4
s.get('Kwie')
s
Out[18]:
{'???': 13,
 'Cze': 6,
 'Gru': 12,
 'Kwie': 4,
 'Lip': 7,
 'Lis': 11,
 'Lut': 2,
 'Maj': 5,
 'Mar': 3,
 'Paz': 10,
 'Sie': 8,
 'Sty': 1,
 'Wrz': 9}

usuwanie pary klucz:wartosc ze slownika

In [19]:
del s['???']
s
Out[19]:
{'Cze': 6,
 'Gru': 12,
 'Kwie': 4,
 'Lip': 7,
 'Lis': 11,
 'Lut': 2,
 'Maj': 5,
 'Mar': 3,
 'Paz': 10,
 'Sie': 8,
 'Sty': 1,
 'Wrz': 9}
In [20]:
s.keys()
Out[20]:
dict_keys(['Paz', 'Lut', 'Lis', 'Lip', 'Sie', 'Wrz', 'Cze', 'Sty', 'Gru', 'Mar', 'Kwie', 'Maj'])
In [21]:
s.values()
Out[21]:
dict_values([10, 2, 11, 7, 8, 9, 6, 1, 12, 3, 4, 5])

pozyteczne funkcje

len - liczebnosc kolekcji

In [ ]:
li = list(range(10))
li
In [ ]:
len(li)
In [ ]:
len({1,2,3})
In [ ]:
s = 'Ala ma kota'
In [ ]:
len(s)
In [ ]:
len(s.split())

min/max - elementy skrajne

In [ ]:
min(li), max(li)
In [ ]:
min(s), max(s)
In [ ]:
min(s.split()), max(s.split())

sum - suma elementów

In [ ]:
sum(li)
In [ ]:
li = s.split()
li
In [ ]:
sum(s)

funkcja zip

zip() to bardzo pozyteczna funkcja sluzaca do parowania odpowiadajacych sobie elementow kolekcji

In [22]:
li = list(zip(('a','b','c'), range(0,3)))
li
Out[22]:
[('a', 0), ('b', 1), ('c', 2)]
In [31]:
li = list(zip(('a','b','c','d'), range(1,5), range(100,110)))
li
Out[31]:
[('a', 1, 100), ('b', 2, 101), ('c', 3, 102), ('d', 4, 103)]

ponowne wywolanie zip() dokona 'rozpiecia' sekwencji. prosze zwrócić uwage na użycie operatora '*', który w tym kontekscie jest operatorem 'odpakowania' kolekcji:

In [35]:
li2 = list(zip(*li))
len(li2)
Out[35]:
3
In [36]:
li2
Out[36]:
[('a', 'b', 'c', 'd'), (1, 2, 3, 4), (100, 101, 102, 103)]
In [49]:
len(li2)
Out[49]:
3
In [50]:
u,v,z = li2
print(u)
print(v)
print(z)
('a', 'b', 'c', 'd')
(1, 2, 3, 4)
(100, 101, 102, 103)
In [ ]:
type(v)

jednym z zastosowań funkcji zip() może być tworzenie słowników:

In [ ]:
v
In [ ]:
dict(zip(u,z))