Python & Strypes

Какво ще правим?

Днес ще си говорим за итератори и генератори! 

Колекции в Python

  • List
  • Tuple
  • Set
  • Dict

List

animals = ['panda', 'dog', 'notcat', 'hatecats']
for animal in animals:
    print('I like {}'.format(animal))

Има подредба! Може да индексираме!

List slicing

a[start:end] # items start through end-1
a[start:]    # items start through the rest of the array
a[:end]      # items from the beginning through end-1
a[start:end:step] # start through not past end, by step
a[:]         # a copy of the whole array

Списъците съдържат "указатели" към елементи

frameworks = ['django', 'angular', 'rails']
frameworks.append(frameworks)

frameworks[-1] is frameworks # True
print(frameworks) # ['django', 'angular', 'rails', [...]]
>>> python_frameworks = ["Django", "Flask"]
>>> frameworks = [python_frameworks, 'angular', 'rails']
>>> frameworks
[['Django', 'Flask'], 'angular', 'rails']
>>> python_frameworks.append("Pyramid")
>>> frameworks
[['Django', 'Flask', 'Pyramid'], 'angular', 'rails']

tuple

Като списък, но не може да се променя

python_frameworks = ("Django", "Flask")
python_frameworks[1] = Pyramid

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> web_framewokrs = (["Django", "Flask"], ["AngularJS", "Dojo"])
>>> web_framewokrs[0].append("Pyramid")
(['Django', 'Flask', 'Pyramid'], ['AngularJS', 'Dojo'])

Set

Просто множества!

hackers = {"Rado", "Kamen", "Ivo"}
set3 = set1 & set2        # Intersection
set4 = set1 | set2        # Union
set5 = set1 - set3        # Set difference
set6 = set1 ^ set2        # Symmetric difference
issubset = set1 <= set2   # Subset test
issuperset = set1 >= set2 # Superset test

Нямаме подредба!

dict

lotr_heroes = {
    'Gandalf': 'the grey',
    'Frodo': 'Baggins',
}
lotr_heroes['Saruman'] = 'the white'

Нямаме подредба!

dict се създава по още няколко начина

>>> dict([('Ivo', '22'), ('Rado', '24'), ('Fandalf', 400)])
{'Rado': '24', 'Fandalf': 400, 'Ivo': '22'}

List comprehension

[израз for променлива in поредица if условие]
[x for x in [1,2,3,4,5,6] if x % 2 == 0]

Как итерираме?

for panda in pandas:
    print(panda.name)

__iter__

__iter__ Връща итератор, с който можем да обходим нашата колекция

__next__ Връща следващата стойност в обхождането

 

iter(strucutre) вика __iter__

next(structure) вика __next__

>>> team = dict([('Ivo', '22'), ('Rado', '24'), ('Fandalf', 400)])
>>> iterator = iter(team)
>>> next(iterator)
'Rado'
>>> next(iterator)
'Fandalf'
>>> next(iterator)
'Ivo'
>>> next(iterator)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> 

iter се опитва да извика __iter__ метода на аргумента си, но ако се окаже, че такъв няма конструира итератор, като просто извиква __getitem__ с последователни естествени числа, започвайки от нула, докато не се хвърли StopIteration

 

class MyMoney:
    def __getitem__(self, index):
        if index > 20:
            raise StopIteration()
        return 30 ** index

>>> ivo_money = MyMoney()
>>> for money in ivo_money:
>>>    print(money)
1
30
900
27000
810000
24300000
729000000
21870000000
656100000000
19683000000000
590490000000000
17714700000000000
531441000000000000
15943230000000000000
478296900000000000000
14348907000000000000000
430467210000000000000000
12914016300000000000000000
387420489000000000000000000
11622614670000000000000000000
348678440100000000000000000000

Мързеливост

Това означава, че всеки елемент се генерира чак когато е необходим.

>>> numbers = [[1,2,3], [1,2,3], [1,2,3]]
>>> sums = map(lambda x: sum(x), numbers)
>>> numbers[2].append(22)
>>> next(sums)
6
>>> next(sums)
6
>>> next(sums)
28

Други мързеливи функции:

  • any
  • all
  • map
  • filter
  • zip
  • enumerate

Итератор pattern!

class FibUpTo:
    def __init__(self, up_to):
        self.up_to = up_to
        self.num = 0
        self.a = 1
        self.b = 1

    def __iter__(self):
        return self

    def __next__(self):
        if self.num > self.up_to:
            raise StopIteration

        if self.num < 2:
            self.num += 1
            return 1
        self.a, self.b = self.b, self.a + self.b
        self.num += 1
        return self.b

fib = FibUpTo(10)

for number in fib:
    print(number)

Генератори

def panda_meals():
    yield 'Bamboo One'
    yield 'Bamboo Two'
    yield 'Bamboo Three'
    yield 'Bamboo Four'
    yield 'Bamboo Five'
    yield 'Bamboo Six'

meals = panda_meals()
for meal in meals:
    print("Num num num " + meal)

И тях ги мързи!

def fib():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

Каква е разликата?

[x for x in [1,2,3,4,5,6] if x % 2 == 0]
(x for x in [1,2,3,4,5,6] if x % 2 == 0)

List Comprehensions

Generator expression

Кое от нещата, които ползваме е мързеливо?

Четене от файл


with open ("text.txt", "r") as myfile:
    for line in myfile:
        print(line)

Четене от база!

cursor.execute('''SELECT name, email, date_of_birth FROM users''')
for row in cursor:
    get_horoscope(row[3])
    send_email(email)
    print('{0} : {1}, {2}'.format(row[0], row[1], row[2]))

Python Strypes Training- Iterators & Generators

By Hack Bulgaria

Python Strypes Training- Iterators & Generators

  • 1,509