#!/usr/bin/env python # coding: utf-8 # In[1]: # В домашней работе вам надо будет сгенерировать свой вариант следующим образом def generate(key, problems=4, variants=4): r = 0 for c in key: r += ord(c) result = [] for j in range(problems): result.append(chr(ord('A') + j) + str(r % variants + 1)) r //= variants return result # In[20]: generate("Зобнин Алексей Игоревич") # In[3]: # Рассмотрим модуль itertools # Подключить его можно так: import itertools # Но тогда придется писать itertools. перед каждым именем функции из этого модуля # Поэтому сделаем так: from itertools import * # Вообще-то так писать в больших проектах не рекомендуется, # чтобы не засорять пространства имен. Лучше подключать только нужные имена # In[5]: s = [1, 2, 3, 4] # In[6]: # Сгенерируем перестановки элементов списка for p in permutations(s): print(p) # In[7]: len(list(itertools.permutations(s))) # In[12]: # Переставлять можно элементы любой итерируемой сущности. Например, буквы в строке for p in permutations("hello"): print(p) # In[13]: len(list(permutations("hello"))) # In[14]: # В предыдущем списке были повторы из-за повторяющейся буквы l # Контейнер set позволяет от них избавиться len(set(permutations("hello"))) # In[15]: # Следующая функция - itertools.combinations # Это сочетания из k элементов for comb in combinations("abcd", 2): print(comb) # In[18]: for comb in combinations("dcba", 3): print(comb) # In[19]: # Сочетания с повторениями for comb in combinations_with_replacement("abcd", 3): print(comb) # In[21]: # Что еще есть в модуле itertools? dir(itertools) # In[ ]: # Обратите внимание, что имена с подчеркиваниями - скрытые или зарезервированные # In[22]: # Функция itertools.product - декартово произведение for elem in product([1,2,3], "ab"): print(elem) # In[24]: for number in [1,2,3]: for letter in "ab": print(number, letter) # In[23]: l = [[1,2,3], "abc", [3.14, 2.718], "hello"] # In[27]: # Декартово перемножить списки внутри нашего l можно с помощью звездочки: for elem in product(*l): print(elem) # In[28]: # Вопрос из зала: что будет, если не поставить звездочку? Вот ответ: for elem in product(l): print(elem) # In[29]: dir(itertools) # In[37]: # Функция itertools.cycle позволяет бесконечно перебирать элементы по кругу # Мы в этом примере воспользуемся enumerate, чтобы цикл стал конечным for i, elem in enumerate(cycle("abc")): if i > 20: break print(i, elem) # In[38]: # Теперь поговорим о генераторах # Их можно писать как обычные функции, но с оператором yield вместо return # Вот такой генератор будет строить первые n членов арифметической прогрессии def progression(a, d, n): x = a i = 1 while i <= n: yield x x += d i += 1 for elem in progression(2, 3, 10): print(elem) # In[41]: g = progression(2, 3, 10) # In[42]: g # In[43]: dir(g) # In[44]: # На самом деле там внутри есть метод __next__, который неявно вызывается в цикле for g.__next__() # In[45]: g.__next__() # In[46]: g.__next__() # In[47]: g.__next__() # In[48]: g.__next__() # In[49]: g.__next__() # In[50]: g.__next__() # In[51]: g.__next__() # In[52]: g.__next__() # In[53]: g.__next__() # In[54]: # На одиннадцатом шаге происходит исключение StopIteration (мы же просили 10 членов!) g.__next__() # In[58]: # Генератор чисел Фибоначчи (где первые два числа - a и b) def fib(a, b, n): i = 1 while i <= n: yield a a, b = b, a + b i += 1 for elem in fib(1, 1, 10): print(elem) # In[59]: # А вот так можно было бы решить задачу F из контеста про циклы # (про последовательность натуральных чисел, где каждое число i повторяется i раз) # Только учтите, что yield from работает начиная с версии 3.3, а в Контесте - 3.2 def sequence(): i = 1 while True: yield from [i] * i i += 1 # Вот другое решение той же задачи def sequence(): i = 1 while True: for j in in range(i): yield i i += 1 # In[62]: for i, elem in enumerate(sequence()): print(elem) if i >= 5 - 1: break # In[63]: # Вспомним, как мы подсчитывали буквы в строке s = "Студенты Высшей школы экономики" letters = {} for c in s: letters[c] = letters.get(c, 0) + 1 # In[66]: # В модуле collections есть удобный класс Counter, # который уже знает, что 0 - это значение по умолчанию import collections s = "Студенты Высшей школы экономики" letters = collections.Counter() for c in s: letters[c] += 1 # не надо думать о том, есть ли такой ключ в словаре # К тому же, Counter сразу выдает элементы в порядке убывания частоты print(letters) # In[68]: # collections.defaultdict - более общая конструкция: словарь со значением по умолчанию # Counter похож на defaultdict(int) # В этом искусственном примере мы сопоставляем словам множества их букв import collections s = "Студенты Высшей школы экономики" letters = collections.defaultdict(set) for word in s.split(" "): for c in word: letters[word].add(c) print(letters) # In[69]: dir(collections) # In[70]: # Вопрос из зала про queue import queue # In[71]: dir(queue) # In[73]: # Вопрос из зала про range type(range(100)) # In[74]: list(range(100)) # In[75]: list(range(6)) # In[76]: # Вот как можно было бы реализовать генератор range (с одним аргументом) def range(n): i = 0 while i < n: yield i i += 1 for c in range(10): print(c) # In[ ]: