# 2. Iterators¶

## 2.1. What is iterator?¶

• `__iter__()`

• `__next__() -> raise StopIteration`

## 2.2. Iterowanie po obiektach¶

### 2.2.1. Iterowanie po `str`¶

```for character in 'hello':
print(character)

# h
# e
# l
# l
# o
```

### 2.2.2. Iterowanie po `list()`, `dict()`, `set()`, `tuple()`¶

```for liczba in [1, 2, 3, 4]:
print(liczba)
```
```for key, value in [('a',1), ('b',2), ('c',3)]:
print(f'{key} -> {value}')

# a -> 1
# b -> 2
# c -> 3
```
```my_dict = {'a': 1, 'b': 2, 'c': 3}

for key in my_dict:
value = my_dict.get(key)
print(value)

# 1
# 2
# 3

for key, value in my_dict.items():
print(f'{key} -> {value}')

# a -> 1
# b -> 2
# c -> 3
```

## 2.3. Własny iterator¶

```class ListaFigurGeometrycznych:
lista = []
aktualny_elemtent = 0

def __iter__(self):
self.aktualny_elemtent = 0
return self

def push(self, figura):
self.lista.append(figura)

def __next__(self):
if self.aktualny_elemtent >= len(self.lista):
raise StopIteration

element = self.lista[self.aktualny_elemtent]
self.aktualny_elemtent += 1
return element

figury = ListaFigurGeometrycznych()

figury.push('prostokat')
figury.push('trojkat')

for figura in figury:
print(figura)
```
```class Parking:
def __init__(self):
self.zaparkowane_samochody = []
self.index = 0

def zaparkuj(self, samochod):
self.zaparkowane_samochody.append(samochod)

def __iter__(self):
self.index = 0
return self

def __next__(self):
if self.index >= len(self.zaparkowane_samochody):
raise StopIteration

samochod = self.zaparkowane_samochody[self.index]
self.index += 1
return samochod

parking = Parking()
parking.zaparkuj('Mercedes')
parking.zaparkuj('Maluch')
parking.zaparkuj('Toyota')

for samochod in parking:
print(samochod)
```

## 2.4. `itertools`¶

```from itertools import cycle

DATA = [
{'last_name': 'Jiménez'},
{'first_name': 'Mark', 'last_name': 'Watney'},
{'first_name': 'Иван'},
{'first_name': 'Jan', 'last_name': 'Twardowski', 'born': 1961},
{'first_name': 'Melissa', 'last_name': 'Lewis', 'first_step': 1969},
]

def get_species(species):
for record in DATA:
if record[4] == species:
yield record

data = get_species('setosa')

cycle(data)
```

```def parzyste_f4():
for x in range(0, 30):
if x % 2 == 0:
yield float(x)

print(parzyste_f4())
a = parzyste_f4()

try:
print('next1', a.__next__())
print('next2', a.__next__())
print('next3', a.__next__())
print('next4', a.__next__())
except StopIteration:
pass

for liczba in parzyste_f4():
print(liczba)
```

## 2.6. Assignments¶

### 2.6.1. Range¶

• Filename: `iterator_range.py`

• Lines of code to write: 5 lines

• Estimated time of completion: 10 min

1. Zaimplementuj własne rozwiązanie `range()` wykorzystując iterator.

2. Początek, koniec, krok (step)

• Filename: `iterator_addressbook.py`

• Lines of code to write: 20 lines

• Estimated time of completion: 15 min

• Input data: Listing 2.82.

Listing 2.82. Struktury danych książki adresowej
```class Kontakt:
self.imie = imie
self.nazwisko = nazwisko

def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)