Тип данных, реализующий последовательность, это такой тип данных, для которого доступен оператор вхождения, функция получения длины (len()), получения среза и к нему можно доступаться как к итератору. Мы уже рассмотрели тип str, в будущем будут рассмотрены bytearray и bites, а на данный момент сосредоточимся на tuple и лист. Все эти типы являются встроенными.
#### Кортежи
Кортежем (tuple) называется упорядоченная последовательность из 0 или более ссылок на объекты. Кортежи поддерживают тот же оператор извлечения среза, что и строки. Кортежи являются неизменяемыми, так что если в ходе работы вам необходима изменяемая последовательность — обратитесь к списком, либо преобразуйте кортеж в список при помощи вызова list().
Как и всегда, tuple может быть вызван как функция. Без передачи аргумента, будет возвращен пустой объект. При передачи в качестве аргумента объекта типа tuple, будет создана его поверхностная копия. Во всех остальных случаях будет совершена попытка привести аргумент к типу tuple. Данная функция принимает не более одного аргумента.
Кортежи могут быть созданы заключением элементов в скобки (даже если элементов нет () — пустой кортеж) или перечислением элементов кортежа через запятую (только не при передачи таким образом кортежа в качестве аргумента функции.
Для кортежей доступны всего два метода: count и index. t.count(x) возвращает число вхождений x в t, а t.index(x) возвращает индекс самого левого вхождения x в t, либо возбуждает ValueError, если x не входит в t. К тому же, для кортежей доступны операторы + (конкатенация), \* (повторение), [] (взятие среза), in и not in (проверка на вхождение). Комбинированные версии присваивания += и \*= могут использоваться, несмотря на то, что кортежи неизменяемы. Просто будет создан новый объект, который будет присвоен переменной (то же происходит и со строками). Для кортежей доступны операции сравнения: <<===!=>= >. Они выполняют сравнение поэлементно и рекурсивно.
Кортежи позволяют выполнить один из самых известных трюков в Python:
```python
x=1
y=2
x,y=y,x
print(x,y)
```
2 1
Также, если элементами итератора являются кортежи, то вы их сразу можете распаковывать:
Список есть упорядоченная последовательность из нуля или более ссылок на объекты. Как и кортежи, для списков доступно взятие среза. Но в отличие от кортежей, списки изменяемы. Как следствие, мы можем изменять не только список целиком или его отдельные элементы, но и целые срезы в нем.
Тип list может быть вызван как функция. Без аргументов list() вернет пустой список. Если в качестве аргумента был передан объект типа list, то будет создана его поверхностная копия. Если аргумент дан, но не является объектом класса list, то будет произведена попытка приведения его к типу list. Данная функция принимает не более одного аргумента.
Списки могут быть созданы также перечислением элементов через запятую в квадратных скобках или при помощи генераторов списков.
Для типа list доступны операции сравнения, работают аналогично случаю с кортежами.
Списки могут быть вложены в друг друга, проитерированы, от них можно взять срез, — все то же, что и для кортежей. Можно использовать операторы in, not int, +, +=, *, *=, функцию len() и конструкцию del.
Также есть оператор \*, который может использоваться для получения остальной части списка в случае выбора нескольких элементов:
| L.append(x) | Добавляет элемент x в конец списка L |
| L.count(x) | Подсчитывает число вхождений элемента x в список L |
| L.extend(m) | Добавляет элементы m, к которому должен быть обеспечен доступ как к итератору, в конец списка L (то же, что и L += m |
| L.index(x, start, end) | Возвращает индекс самого левого вхождения x в L. Если start и end заданы, то поиск происходит в срезе L[start:end]. Если элемент не найден, то возбуждается исключение ValueError |
| L.insert(i, x) | Вставляет элемент x на позицию с индексом i в список L |
| L.pop() | Удаляет последний элемент списка L и возвращает его |
| L.pop(i) | Удаляет элемент списка L с индексом i и возвращает его |
| L.remove(x) | Удаляет самое левое вхождение элемента x из списка L. Если элемент не найден, то возбуждается исключение ValueError |
| L.reverse() | Разворачивает список |
| L.sort(...) | Сортирует список. Аргумент key отвечает за функцию порядка, а reversed за способ сортировки (по невозрастанию / неубыванию) |
#### Генераторы списков
Для получения списка как результат какой-то операции над итератором используются генераторы списков. Есть две формымы генератора списков:
[выражение for элемент in итератор]
[выражение for элемент in итератор if условие]
В самом простом случае выражение и есть элемент:
```python
print([xforxinrange(10)])
print([2*xforxinrange(10)])
print([2*xforxinrange(10)ifx%3==0])
```
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
[0, 6, 12, 18]
Последняя форма в разы удобнее, чем запись:
```python
lst=[]
forxinrange(10):
ifx%3==0:
lst.append(2*x)
print(lst)
```
[0, 6, 12, 18]
### Раздел 2. Типы-множества
Типы данных-множества — типы, для которых доступны оператор вхождения in, функция len и доступ, как к итератору. В Python есть два типа множеств — set и frozenset. Тип frozenset является неизменяемым, поэтому для него недоступны методы для типа set, которые изменяют объект. В остальном они идентичны.
Только хешируемые объекты могут быть добавлены в множество. Все встроенные неизменяемые типы являются хешируемыми.
#### Множества
Множество типа set есть неупорядоченная коллекция из нуля или более ссылок на хешируемые объекты. Множества изменяемы, так что в них можно добавлять и удалять элементы. Будучи неупорядоченными, понятие индекса или позиции для них не имеет смысла.
Для создания множества используется либо вызов set(), который без аргументов создает пустое множество. С аргументом типа set создается поверхностная копия множества, а с другим аргументом выполняется попытка приведения к множеству. Данная функция не принимает более одного аргумента. Множество может быть также создано путем заключения элементов в фигурные скобки, но стоит учитывать, что пустое множество не может быть создано таким образом, так как {} создаст пустой словарь.
Множества поддерживают функцию len(), которое возвращает число элементов множества.
Для типа set доступны следующие методы:
| Метод | Описание |
| ----- | :------- |
| s.add(x) | Добавляет элемент x во множество s, если такого там нет |
| s.clear() | Удаляет все элементы множества s |
| s.copy() | Создает неглубокую копию множества s |
| s.difference(t) | Возвращает новое множество, которое содержит все элементы множества s, которые не входят во множество t. Эквивалент s - t |
| s.differenct_update(t) | Удаляет все элементы t из множества s. Эквивалент s -= t |
| s.discard(x) | Удаляет элемент x из множества s |
| s.intersection(t) | Возвращает новое множество, которое содержит элементы множества s, которые в то же время являются элементами множества t. Эквивалент s & t |
| s.intersection_update(t) | Удаляет из множества s все элементы, которые не входят в t. Эквивалент s &= t |
| s.isdisjoint(t) | Возвращает True, если у множеств s и t нет общих элементов |
| s.issubset(t) | Возвращает True, если s есть подмножество (несобственное) t. Эквивалент s <= t |
| s.issuperset(t) | Возвращает True, если t есть подмножество (несобственное) s. Эквивалент t <= s |
| s.pop() | Удаляет случайный элемент s и возвращает его. Возбуждает исключение KeyError, если множесво пустое |
| s.remove(x) | Удаляет элемент x из множества s. Возбуждает исключение KeyError, если x не входит в s |
| s.symmetric_difference(t) | Возвращает новое множество, которое содержит элементы, которые либо содержатся в s и не содержатся в t, либо содержатся в t и не содержатся в s. Эквивалент s ^ t |
| s.symmetric_difference_update(t) | Записывает в s симметрическую разность s и t. Эквивалент s ^= t |
| s.union(t) | Возвращает новое множество, которое содержит все элементы множеств s и t |
| s.update(t) | Добавляет все элементы множества t во множество s |
Последние два метода эквивалентны s | t и s |= t соответственно.
#### Генераторы множеств
В целом то же, что и для списков, но сам генератор обозначается фигурными скобками:
```python
print({xforxinrange(10)})
print({2*xforxinrange(10)})
print({2*xforxinrange(10)ifx%3==0})
```
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
{0, 2, 4, 6, 8, 10, 12, 14, 16, 18}
{0, 18, 12, 6}
### Раздел 3. Типы-отображения
Типы отображения — наборы пар "ключ - значение". Единственным встроенным типом-отображением является dictionary, который отображает хешируемые объекты на ссылки на другие объекты.
#### Словари
Тип dict (словарь) это упорядоченная коллекция пар "ключ - значение". Раньше dict был неупорядоченным типом, поэтому во избежания ошибок при исполнении кода более старыми интерпретаторами, советую вам придерживаться отношения к словорям как к неупорядоченным последовательностям.
Словари поддерживают оператор вхождения in, функцию len(), и доступ как к итератору. Среди операций сравнения поддерживаются только == и !=.
Как и обычно, тип dict может быть вызван как функция. Если ей не переданы аргументы, то создается пустой словарь. Если передан аргумент с типом-отображением, то создается словарь на основе этого аргумента. Например, если аргумент типа dict, то будет создана его поверхностная копия. Можно также передать аргумент-последовательность, каждый элемент в котором — последовательность из двух элементов: ключа и значения. Также пустой словарь можно создать при помощи конструкции {}, а словарь с элементами — перечислив пары ключ - значение в фигурных скобках через запятую, отделяя ключи от значений двоеточием:
{ключ1 : значение1, ключ2 : значение2}
К тому же доступны генераторы словарей.
Мы можем доступаться к элементам словаря, используя ключ: d[ключ] вернет значение элемента с ключем *ключ*.
Для добавления новых элементов используется оператор присваивания: d[новый\_ключ] = новое\_значение.
Для типа dict доступны следующие методы:
| Метод | Описание |
| ----- | :------- |
| d.clear() | Удаляет все элементы словаря d |
| d.copy() | Возвращает поверхностную копию словаря d |
| d.fromkeys(s, v) | Возвращает словарь, где ключами являются элементы последователности s, а значения равны v или None, если v не указано |
| d.get(k) | Возвращает значение, которое соответствует ключу k или None, если такого нет |
| d.get(k, v) | Возвращает значение, которое соответствует ключу k или v, если такого нет |
| d.items() | Возвращает view (read-only итератор), содержащий пары (ключ, значение) словаря d |
| d.keys() | Возвращает view, содержащий ключи словаря d |
| d.pop(k) | Удаляет элемент, соответствующий ключу k и возвращает его. Если такого нет, то возбуждается исключение KeyError |
| d.pop(k, v) | Удаляет элемент, соответствующий ключу k и возвращает его. Если такого нет, то возвращается значение v |
| d.popitem() | Удаляет из словаря d и возвращает некоторую пару (ключ, значение). Возбуждает исключение KeyError, если d пуст |
| d.setdefault(k, v) | ТТо же, что и d.get(k), но если такого элемента нет, то создается новый со значением None или v, если указано |
| d.values() | Возвращает view всех значений словаря d |
#### Генераторы словарей
Генераторы словарей имеют две уже знакомые нам формы:
[выражение\_ключа : выражение\_значения for ключ, значение in итератор]
[выражение\_ключа : выражение\_значения for ключ, значение in итератор if условие]
### Раздел 4. Итераторы. Функции и операци для работы с итераторами
Тип данных называется итерируемым, если он может возвращать свои элементы по одному. Технически, любой объект, реализующий метод \_\_iter\_\_() является итерируемым и может предоставить итератор. Итератор — объект, реализуюзий метод \_\_next()\_\_, возвращающий следующее значение и возбуждающий исключение StopIteration, если элементов больше нет.
Для итерируемых объектов доступны следующие функции и операторы:
| Функция или оператор | Описание |
| -------------------- | :------- |
| s + t | Возвращает конкатенацию последовательностей s и t |
| s * n | Возвращает последовательность, которая является результатом повторения последовательности s n раз |
| x in t | Проверяет, есть ли в последовательности i элемент x |
| all(i) | Возвращает True, если все элементы i при приведении к типу bool имеют значение True |
| any(i) | Возвращает True, если один из элементов i при приведении к типу bool имеет значение True |
| enumerate(i, start) | Возвращает последовательность элементов (индекс, значение) для итератора i, начиная с индекса 0 или start, если данный аргумент задан |
| len(x) | Возвращает число элементов в x |
| max(i, key) | Возвращает максимальный элемент в i. Если аргумент key задан, то возвращает элемент, для которого key максимален |
| min(i, key) | Возвращает минимальный элемент в i. Если аргумент key задан, то возвращает элемент, для которого key минимален |
| range(start, stop, step) | Возвращает итератор, содержащий целые числа от start до stop с шагом step. Аргумент start включен в последовательность, а stop — нет |
| reversed(i) | Возвращает итератор, в котором элементы идут в обратном порядке |
| sorted(i, key, reverse) | Возвращает отсортированный по неубыванию итератор. Если задан аргумент key, то сортировка идет по значением key(x) для каждого элемента x. Если reversre указан как True, то сортировка идет по невозрастанию |
| sum(i, start) | Возвращает сумму элементов в итераторе i плюс start. Если start не задан, то принимается равным 0 |
| zip(i1, ..., iN) | Возвращает итератор из кортежей, состоящий из элементов i1, ..., iN. Количество кортежей определяется минимальной длиной i1, ..., iN |
### Раздел 5. Копирование коллекций
При присваивании объектов будет выполнено присваивание по ссылке:
```python
x=['Nightwing','Robin','Catwoman']
y=x
x[0]='Alfred'
print(y)
```
['Alfred', 'Robin', 'Catwoman']
Для создания поверхностной копии можно использовать оператор среза:
```python
x=['Nightwing','Robin','Catwoman']
y=x[:]
x[0]='Alfred'
print(y)
```
['Nightwing', 'Robin', 'Catwoman']
Но поверхностная копия имеет ограничения, связанные с тем, что при ее создании создаются копии лишь самих элементов. Если они в свою очередь являются ссылками, то мы снова столкнемся с проблемой:
Есть достаточно интересный модуль vedis, который предоставляет доступ к key-value store типа Redis на диске, но при этом API этого доступа совпадает с доступом к словарю.
Решим с использованием модуля vedis [задачу о гипотезе Колатца](https://lambda-it.ru/post/26) и сделаем визуализацию при помощи matplotlib.
Для начала напишем функцию, которая из текущего числа получает следующее в последовательности:
```python
defnext_kolatz(x):
ifx&1:
return3*x+1
returnx>>1
```
Если число x является нечетным (последний разряд в двоичной системе равен единице), то мы возвращаем 3x + 1. В противном случае, мы делим число на 2 (соответствует сдвигу вправо на один разряд в двоичной системе счисления). Теперь импортируем модуль vedis. При помощи него мы будем хранить длину цепочки для чисел, которые мы уже встречали. Также напишем функцию, которая вычисляет и возвращает длину цепочки для заданного числа x, записывает ее в хранилище, а также записывает в хранилище длины цепочек для всех промежуточных чисел:
```python
defget_kolatz_length(x,storage):
cur=x
try:
returnint(storage.get(cur))
exceptKeyErrorase:
pass
stack=[cur]
whileTrue:
cur=next_kolatz(cur)
try:
length=int(storage.get(cur))
break
exceptKeyErrorase:
pass
stack.append(cur)
foriteminstack[::-1]:
length+=1
storage.set(item,length)
returnint(storage.get(x))
```
Теперь напишем функцию, которая возвращает число, меньшее заданного, для которого данная цепочка максимальна и длину цепочки:
Теперь остается только инициализировать хранилище и испытать наши функции:
```python
fromvedisimportVedis
db=Vedis('storage.db')
db.set(1,1)
print(get_max_kolatz_length(100000,db))
db.close()
```
(77031, 351)
True
Теперь построим обычный scatter plot при помощи matplotlib:
```python
importmatplotlib.pyplotasplt
db=Vedis('storage.db')
X=range(1,101)
Y=[get_kolatz_length(x,db)forxinX]
db.close()
plt.scatter(X,Y)
plt.title('Визуализация длин цепочек Колатца')
plt.xlabel('Число')
plt.ylabel('Длина цепочки')
plt.show()
```

### Раздел 7. Домашнее задание
Решить задачи после третьей главы Саммерфилда
Загуглить гипотезу Гольдбаха
Загуглить динамическое программирование
Написать функцию, которая принимает в качестве аргумента множество и функцию и при помощи matplotlib изображает график заданной функции на множестве значений. Добавьте несколько дополнительных аргументов: например, возможность сделать одну из осей логарифмической, выбрать разные цветовые схемы, разные типы графиков и т.д.
Решить задачу, которая будет опубликована в субботу
"Тип данных, реализующий последовательность, это такой тип данных, для которого доступен оператор вхождения, функция получения длины (len()), получения среза и к нему можно доступаться как к итератору. Мы уже рассмотрели тип str, в будущем будут рассмотрены bytearray и bites, а на данный момент сосредоточимся на tuple и лист. Все эти типы являются встроенными.\n",
"\n",
"#### Кортежи\n",
"\n",
"Кортежем (tuple) называется упорядоченная последовательность из 0 или более ссылок на объекты. Кортежи поддерживают тот же оператор извлечения среза, что и строки. Кортежи являются неизменяемыми, так что если в ходе работы вам необходима изменяемая последовательность — обратитесь к списком, либо преобразуйте кортеж в список при помощи вызова list().\n",
"\n",
"Как и всегда, tuple может быть вызван как функция. Без передачи аргумента, будет возвращен пустой объект. При передачи в качестве аргумента объекта типа tuple, будет создана его поверхностная копия. Во всех остальных случаях будет совершена попытка привести аргумент к типу tuple. Данная функция принимает не более одного аргумента.\n",
"\n",
"Кортежи могут быть созданы заключением элементов в скобки (даже если элементов нет () — пустой кортеж) или перечислением элементов кортежа через запятую (только не при передачи таким образом кортежа в качестве аргумента функции.\n",
"\n",
"Для кортежей доступны всего два метода: count и index. t.count(x) возвращает число вхождений x в t, а t.index(x) возвращает индекс самого левого вхождения x в t, либо возбуждает ValueError, если x не входит в t. К тому же, для кортежей доступны операторы + (конкатенация), \\* (повторение), [] (взятие среза), in и not in (проверка на вхождение). Комбинированные версии присваивания += и \\*= могут использоваться, несмотря на то, что кортежи неизменяемы. Просто будет создан новый объект, который будет присвоен переменной (то же происходит и со строками). Для кортежей доступны операции сравнения: < <= == != >= >. Они выполняют сравнение поэлементно и рекурсивно.\n",
"\n",
"Кортежи позволяют выполнить один из самых известных трюков в Python:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2 1\n"
]
}
],
"source": [
"x = 1\n",
"y = 2\n",
"\n",
"x, y = y, x\n",
" \n",
"print(x, y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Также, если элементами итератора являются кортежи, то вы их сразу можете распаковывать:"
"Список есть упорядоченная последовательность из нуля или более ссылок на объекты. Как и кортежи, для списков доступно взятие среза. Но в отличие от кортежей, списки изменяемы. Как следствие, мы можем изменять не только список целиком или его отдельные элементы, но и целые срезы в нем.\n",
"\n",
"Тип list может быть вызван как функция. Без аргументов list() вернет пустой список. Если в качестве аргумента был передан объект типа list, то будет создана его поверхностная копия. Если аргумент дан, но не является объектом класса list, то будет произведена попытка приведения его к типу list. Данная функция принимает не более одного аргумента.\n",
"\n",
"Списки могут быть созданы также перечислением элементов через запятую в квадратных скобках или при помощи генераторов списков.\n",
"\n",
"Для типа list доступны операции сравнения, работают аналогично случаю с кортежами.\n",
"\n",
"Списки могут быть вложены в друг друга, проитерированы, от них можно взять срез, — все то же, что и для кортежей. Можно использовать операторы in, not int, +, +=, *, *=, функцию len() и конструкцию del.\n",
"\n",
"Также есть оператор \\*, который может использоваться для получения остальной части списка в случае выбора нескольких элементов:"
"| L.append(x) | Добавляет элемент x в конец списка L |\n",
"| L.count(x) | Подсчитывает число вхождений элемента x в список L |\n",
"| L.extend(m) | Добавляет элементы m, к которому должен быть обеспечен доступ как к итератору, в конец списка L (то же, что и L += m |\n",
"| L.index(x, start, end) | Возвращает индекс самого левого вхождения x в L. Если start и end заданы, то поиск происходит в срезе L[start:end]. Если элемент не найден, то возбуждается исключение ValueError |\n",
"| L.insert(i, x) | Вставляет элемент x на позицию с индексом i в список L |\n",
"| L.pop() | Удаляет последний элемент списка L и возвращает его |\n",
"| L.pop(i) | Удаляет элемент списка L с индексом i и возвращает его |\n",
"| L.remove(x) | Удаляет самое левое вхождение элемента x из списка L. Если элемент не найден, то возбуждается исключение ValueError |\n",
"| L.reverse() | Разворачивает список |\n",
"| L.sort(...) | Сортирует список. Аргумент key отвечает за функцию порядка, а reversed за способ сортировки (по невозрастанию / неубыванию) |\n",
"\n",
"#### Генераторы списков\n",
"\n",
"Для получения списка как результат какой-то операции над итератором используются генераторы списков. Есть две формымы генератора списков:\n",
"\n",
"[выражение for элемент in итератор]\n",
"\n",
"[выражение for элемент in итератор if условие]\n",
"\n",
"В самом простом случае выражение и есть элемент:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
"[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]\n",
"[0, 6, 12, 18]\n"
]
}
],
"source": [
"print([x for x in range(10)])\n",
"print([2*x for x in range(10)])\n",
"print([2*x for x in range(10) if x % 3 == 0])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Последняя форма в разы удобнее, чем запись:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0, 6, 12, 18]\n"
]
}
],
"source": [
"lst = []\n",
"for x in range(10):\n",
" if x % 3 == 0:\n",
" lst.append(2*x)\n",
"print(lst)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Раздел 2. Типы-множества\n",
"\n",
"Типы данных-множества — типы, для которых доступны оператор вхождения in, функция len и доступ, как к итератору. В Python есть два типа множеств — set и frozenset. Тип frozenset является неизменяемым, поэтому для него недоступны методы для типа set, которые изменяют объект. В остальном они идентичны.\n",
"\n",
"Только хешируемые объекты могут быть добавлены в множество. Все встроенные неизменяемые типы являются хешируемыми.\n",
"\n",
"#### Множества\n",
"\n",
"Множество типа set есть неупорядоченная коллекция из нуля или более ссылок на хешируемые объекты. Множества изменяемы, так что в них можно добавлять и удалять элементы. Будучи неупорядоченными, понятие индекса или позиции для них не имеет смысла.\n",
"\n",
"Для создания множества используется либо вызов set(), который без аргументов создает пустое множество. С аргументом типа set создается поверхностная копия множества, а с другим аргументом выполняется попытка приведения к множеству. Данная функция не принимает более одного аргумента. Множество может быть также создано путем заключения элементов в фигурные скобки, но стоит учитывать, что пустое множество не может быть создано таким образом, так как {} создаст пустой словарь.\n",
"Множества поддерживают функцию len(), которое возвращает число элементов множества.\n",
"\n",
"Для типа set доступны следующие методы:\n",
"\n",
"| Метод | Описание |\n",
"| ----- | :------- |\n",
"| s.add(x) | Добавляет элемент x во множество s, если такого там нет |\n",
"| s.clear() | Удаляет все элементы множества s |\n",
"| s.copy() | Создает неглубокую копию множества s |\n",
"| s.difference(t) | Возвращает новое множество, которое содержит все элементы множества s, которые не входят во множество t. Эквивалент s - t |\n",
"| s.differenct_update(t) | Удаляет все элементы t из множества s. Эквивалент s -= t |\n",
"| s.discard(x) | Удаляет элемент x из множества s |\n",
"| s.intersection(t) | Возвращает новое множество, которое содержит элементы множества s, которые в то же время являются элементами множества t. Эквивалент s & t |\n",
"| s.intersection_update(t) | Удаляет из множества s все элементы, которые не входят в t. Эквивалент s &= t |\n",
"| s.isdisjoint(t) | Возвращает True, если у множеств s и t нет общих элементов |\n",
"| s.issubset(t) | Возвращает True, если s есть подмножество (несобственное) t. Эквивалент s <= t |\n",
"| s.issuperset(t) | Возвращает True, если t есть подмножество (несобственное) s. Эквивалент t <= s |\n",
"| s.pop() | Удаляет случайный элемент s и возвращает его. Возбуждает исключение KeyError, если множесво пустое |\n",
"| s.remove(x) | Удаляет элемент x из множества s. Возбуждает исключение KeyError, если x не входит в s |\n",
"| s.symmetric_difference(t) | Возвращает новое множество, которое содержит элементы, которые либо содержатся в s и не содержатся в t, либо содержатся в t и не содержатся в s. Эквивалент s ^ t |\n",
"| s.symmetric_difference_update(t) | Записывает в s симметрическую разность s и t. Эквивалент s ^= t |\n",
"| s.union(t) | Возвращает новое множество, которое содержит все элементы множеств s и t |\n",
"| s.update(t) | Добавляет все элементы множества t во множество s |\n",
"\n",
"Последние два метода эквивалентны s | t и s |= t соответственно.\n",
"\n",
"#### Генераторы множеств\n",
"\n",
"В целом то же, что и для списков, но сам генератор обозначается фигурными скобками:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}\n",
"{0, 2, 4, 6, 8, 10, 12, 14, 16, 18}\n",
"{0, 18, 12, 6}\n"
]
}
],
"source": [
"print({x for x in range(10)})\n",
"print({2*x for x in range(10)})\n",
"print({2*x for x in range(10) if x % 3 == 0})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Раздел 3. Типы-отображения\n",
"\n",
"Типы отображения — наборы пар \"ключ - значение\". Единственным встроенным типом-отображением является dictionary, который отображает хешируемые объекты на ссылки на другие объекты.\n",
"\n",
"#### Словари\n",
"\n",
"Тип dict (словарь) это упорядоченная коллекция пар \"ключ - значение\". Раньше dict был неупорядоченным типом, поэтому во избежания ошибок при исполнении кода более старыми интерпретаторами, советую вам придерживаться отношения к словорям как к неупорядоченным последовательностям.\n",
"\n",
"Словари поддерживают оператор вхождения in, функцию len(), и доступ как к итератору. Среди операций сравнения поддерживаются только == и !=.\n",
"\n",
"Как и обычно, тип dict может быть вызван как функция. Если ей не переданы аргументы, то создается пустой словарь. Если передан аргумент с типом-отображением, то создается словарь на основе этого аргумента. Например, если аргумент типа dict, то будет создана его поверхностная копия. Можно также передать аргумент-последовательность, каждый элемент в котором — последовательность из двух элементов: ключа и значения. Также пустой словарь можно создать при помощи конструкции {}, а словарь с элементами — перечислив пары ключ - значение в фигурных скобках через запятую, отделяя ключи от значений двоеточием:\n",
"\n",
"{ключ1 : значение1, ключ2 : значение2}\n",
"\n",
"К тому же доступны генераторы словарей.\n",
"\n",
"Мы можем доступаться к элементам словаря, используя ключ: d[ключ] вернет значение элемента с ключем *ключ*.\n",
"\n",
"Для добавления новых элементов используется оператор присваивания: d[новый\\_ключ] = новое\\_значение.\n",
"\n",
"Для типа dict доступны следующие методы:\n",
"\n",
"| Метод | Описание |\n",
"| ----- | :------- |\n",
"| d.clear() | Удаляет все элементы словаря d |\n",
"| d.copy() | Возвращает поверхностную копию словаря d |\n",
"| d.fromkeys(s, v) | Возвращает словарь, где ключами являются элементы последователности s, а значения равны v или None, если v не указано |\n",
"| d.get(k) | Возвращает значение, которое соответствует ключу k или None, если такого нет |\n",
"| d.get(k, v) | Возвращает значение, которое соответствует ключу k или v, если такого нет |\n",
"| d.items() | Возвращает view (read-only итератор), содержащий пары (ключ, значение) словаря d |\n",
"| d.keys() | Возвращает view, содержащий ключи словаря d |\n",
"| d.pop(k) | Удаляет элемент, соответствующий ключу k и возвращает его. Если такого нет, то возбуждается исключение KeyError |\n",
"| d.pop(k, v) | Удаляет элемент, соответствующий ключу k и возвращает его. Если такого нет, то возвращается значение v |\n",
"| d.popitem() | Удаляет из словаря d и возвращает некоторую пару (ключ, значение). Возбуждает исключение KeyError, если d пуст |\n",
"| d.setdefault(k, v) | ТТо же, что и d.get(k), но если такого элемента нет, то создается новый со значением None или v, если указано |\n",
"| d.values() | Возвращает view всех значений словаря d |\n",
"\n",
"#### Генераторы словарей\n",
"\n",
"Генераторы словарей имеют две уже знакомые нам формы:\n",
"\n",
"[выражение\\_ключа : выражение\\_значения for ключ, значение in итератор]\n",
"\n",
"[выражение\\_ключа : выражение\\_значения for ключ, значение in итератор if условие]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Раздел 4. Итераторы. Функции и операци для работы с итераторами\n",
"\n",
"Тип данных называется итерируемым, если он может возвращать свои элементы по одному. Технически, любой объект, реализующий метод \\_\\_iter\\_\\_() является итерируемым и может предоставить итератор. Итератор — объект, реализуюзий метод \\_\\_next()\\_\\_, возвращающий следующее значение и возбуждающий исключение StopIteration, если элементов больше нет.\n",
"\n",
"Для итерируемых объектов доступны следующие функции и операторы:\n",
"\n",
"| Функция или оператор | Описание |\n",
"| -------------------- | :------- |\n",
"| s + t | Возвращает конкатенацию последовательностей s и t |\n",
"| s * n | Возвращает последовательность, которая является результатом повторения последовательности s n раз |\n",
"| x in t | Проверяет, есть ли в последовательности i элемент x |\n",
"| all(i) | Возвращает True, если все элементы i при приведении к типу bool имеют значение True |\n",
"| any(i) | Возвращает True, если один из элементов i при приведении к типу bool имеет значение True |\n",
"| enumerate(i, start) | Возвращает последовательность элементов (индекс, значение) для итератора i, начиная с индекса 0 или start, если данный аргумент задан |\n",
"| len(x) | Возвращает число элементов в x |\n",
"| max(i, key) | Возвращает максимальный элемент в i. Если аргумент key задан, то возвращает элемент, для которого key максимален |\n",
"| min(i, key) | Возвращает минимальный элемент в i. Если аргумент key задан, то возвращает элемент, для которого key минимален |\n",
"| range(start, stop, step) | Возвращает итератор, содержащий целые числа от start до stop с шагом step. Аргумент start включен в последовательность, а stop — нет |\n",
"| reversed(i) | Возвращает итератор, в котором элементы идут в обратном порядке |\n",
"| sorted(i, key, reverse) | Возвращает отсортированный по неубыванию итератор. Если задан аргумент key, то сортировка идет по значением key(x) для каждого элемента x. Если reversre указан как True, то сортировка идет по невозрастанию |\n",
"| sum(i, start) | Возвращает сумму элементов в итераторе i плюс start. Если start не задан, то принимается равным 0 |\n",
"| zip(i1, ..., iN) | Возвращает итератор из кортежей, состоящий из элементов i1, ..., iN. Количество кортежей определяется минимальной длиной i1, ..., iN |"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Раздел 5. Копирование коллекций\n",
"\n",
"При присваивании объектов будет выполнено присваивание по ссылке:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['Alfred', 'Robin', 'Catwoman']\n"
]
}
],
"source": [
"x = ['Nightwing', 'Robin', 'Catwoman']\n",
"y = x\n",
"x[0] = 'Alfred'\n",
"print(y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Для создания поверхностной копии можно использовать оператор среза:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['Nightwing', 'Robin', 'Catwoman']\n"
]
}
],
"source": [
"x = ['Nightwing', 'Robin', 'Catwoman']\n",
"y = x[:]\n",
"x[0] = 'Alfred'\n",
"print(y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Но поверхностная копия имеет ограничения, связанные с тем, что при ее создании создаются копии лишь самих элементов. Если они в свою очередь являются ссылками, то мы снова столкнемся с проблемой:"
"Есть достаточно интересный модуль vedis, который предоставляет доступ к key-value store типа Redis на диске, но при этом API этого доступа совпадает с доступом к словарю.\n",
"\n",
"Решим с использованием модуля vedis [задачу о гипотезе Колатца](https://lambda-it.ru/post/26) и сделаем визуализацию при помощи matplotlib.\n",
"\n",
"Для начала напишем функцию, которая из текущего числа получает следующее в последовательности:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"def next_kolatz(x):\n",
" if x & 1:\n",
" return 3*x + 1\n",
" return x >> 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Если число x является нечетным (последний разряд в двоичной системе равен единице), то мы возвращаем 3x + 1. В противном случае, мы делим число на 2 (соответствует сдвигу вправо на один разряд в двоичной системе счисления). Теперь импортируем модуль vedis. При помощи него мы будем хранить длину цепочки для чисел, которые мы уже встречали. Также напишем функцию, которая вычисляет и возвращает длину цепочки для заданного числа x, записывает ее в хранилище, а также записывает в хранилище длины цепочек для всех промежуточных чисел:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"def get_kolatz_length(x, storage):\n",
" cur = x\n",
" try:\n",
" return int(storage.get(cur))\n",
" except KeyError as e:\n",
" pass\n",
" stack = [cur]\n",
" while True:\n",
" cur = next_kolatz(cur)\n",
" try:\n",
" length = int(storage.get(cur))\n",
" break\n",
" except KeyError as e:\n",
" pass\n",
" stack.append(cur)\n",
" for item in stack[::-1]:\n",
" length += 1\n",
" storage.set(item, length)\n",
" return int(storage.get(x))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Теперь напишем функцию, которая возвращает число, меньшее заданного, для которого данная цепочка максимальна и длину цепочки:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"def get_max_kolatz_length(n, storage):\n",
" num = max(range(1, n+1), key=lambda x: get_kolatz_length(x, storage))\n",
" return num, get_kolatz_length(num, storage)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Теперь остается только инициализировать хранилище и испытать наши функции:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(77031, 351)\n"
]
},
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from vedis import Vedis\n",
"\n",
"db = Vedis('storage.db')\n",
"db.set(1, 1)\n",
"\n",
"print(get_max_kolatz_length(100000, db))\n",
"db.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Теперь построим обычный scatter plot при помощи matplotlib:"
"Решить задачи после третьей главы Саммерфилда\n",
"\n",
"Загуглить гипотезу Гольдбаха\n",
"\n",
"Загуглить динамическое программирование\n",
"\n",
"Написать функцию, которая принимает в качестве аргумента множество и функцию и при помощи matplotlib изображает график заданной функции на множестве значений. Добавьте несколько дополнительных аргументов: например, возможность сделать одну из осей логарифмической, выбрать разные цветовые схемы, разные типы графиков и т.д.\n",
"\n",
"Решить задачу, которая будет опубликована в субботу"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
%% Cell type:markdown id: tags:
# Python
## Типы данных-коллекции
### Раздел 1. Типы данных-последовательности
Тип данных, реализующий последовательность, это такой тип данных, для которого доступен оператор вхождения, функция получения длины (len()), получения среза и к нему можно доступаться как к итератору. Мы уже рассмотрели тип str, в будущем будут рассмотрены bytearray и bites, а на данный момент сосредоточимся на tuple и лист. Все эти типы являются встроенными.
#### Кортежи
Кортежем (tuple) называется упорядоченная последовательность из 0 или более ссылок на объекты. Кортежи поддерживают тот же оператор извлечения среза, что и строки. Кортежи являются неизменяемыми, так что если в ходе работы вам необходима изменяемая последовательность — обратитесь к списком, либо преобразуйте кортеж в список при помощи вызова list().
Как и всегда, tuple может быть вызван как функция. Без передачи аргумента, будет возвращен пустой объект. При передачи в качестве аргумента объекта типа tuple, будет создана его поверхностная копия. Во всех остальных случаях будет совершена попытка привести аргумент к типу tuple. Данная функция принимает не более одного аргумента.
Кортежи могут быть созданы заключением элементов в скобки (даже если элементов нет () — пустой кортеж) или перечислением элементов кортежа через запятую (только не при передачи таким образом кортежа в качестве аргумента функции.
Для кортежей доступны всего два метода: count и index. t.count(x) возвращает число вхождений x в t, а t.index(x) возвращает индекс самого левого вхождения x в t, либо возбуждает ValueError, если x не входит в t. К тому же, для кортежей доступны операторы + (конкатенация), \* (повторение), [] (взятие среза), in и not in (проверка на вхождение). Комбинированные версии присваивания += и \*= могут использоваться, несмотря на то, что кортежи неизменяемы. Просто будет создан новый объект, который будет присвоен переменной (то же происходит и со строками). Для кортежей доступны операции сравнения: <<===!=>= >. Они выполняют сравнение поэлементно и рекурсивно.
Кортежи позволяют выполнить один из самых известных трюков в Python:
%% Cell type:code id: tags:
``` python
x=1
y=2
x,y=y,x
print(x,y)
```
%% Output
2 1
%% Cell type:markdown id: tags:
Также, если элементами итератора являются кортежи, то вы их сразу можете распаковывать:
Список есть упорядоченная последовательность из нуля или более ссылок на объекты. Как и кортежи, для списков доступно взятие среза. Но в отличие от кортежей, списки изменяемы. Как следствие, мы можем изменять не только список целиком или его отдельные элементы, но и целые срезы в нем.
Тип list может быть вызван как функция. Без аргументов list() вернет пустой список. Если в качестве аргумента был передан объект типа list, то будет создана его поверхностная копия. Если аргумент дан, но не является объектом класса list, то будет произведена попытка приведения его к типу list. Данная функция принимает не более одного аргумента.
Списки могут быть созданы также перечислением элементов через запятую в квадратных скобках или при помощи генераторов списков.
Для типа list доступны операции сравнения, работают аналогично случаю с кортежами.
Списки могут быть вложены в друг друга, проитерированы, от них можно взять срез, — все то же, что и для кортежей. Можно использовать операторы in, not int, +, +=, *, *=, функцию len() и конструкцию del.
Также есть оператор \*, который может использоваться для получения остальной части списка в случае выбора нескольких элементов:
| L.append(x) | Добавляет элемент x в конец списка L |
| L.count(x) | Подсчитывает число вхождений элемента x в список L |
| L.extend(m) | Добавляет элементы m, к которому должен быть обеспечен доступ как к итератору, в конец списка L (то же, что и L += m |
| L.index(x, start, end) | Возвращает индекс самого левого вхождения x в L. Если start и end заданы, то поиск происходит в срезе L[start:end]. Если элемент не найден, то возбуждается исключение ValueError |
| L.insert(i, x) | Вставляет элемент x на позицию с индексом i в список L |
| L.pop() | Удаляет последний элемент списка L и возвращает его |
| L.pop(i) | Удаляет элемент списка L с индексом i и возвращает его |
| L.remove(x) | Удаляет самое левое вхождение элемента x из списка L. Если элемент не найден, то возбуждается исключение ValueError |
| L.reverse() | Разворачивает список |
| L.sort(...) | Сортирует список. Аргумент key отвечает за функцию порядка, а reversed за способ сортировки (по невозрастанию / неубыванию) |
#### Генераторы списков
Для получения списка как результат какой-то операции над итератором используются генераторы списков. Есть две формымы генератора списков:
[выражение for элемент in итератор]
[выражение for элемент in итератор if условие]
В самом простом случае выражение и есть элемент:
%% Cell type:code id: tags:
``` python
print([xforxinrange(10)])
print([2*xforxinrange(10)])
print([2*xforxinrange(10)ifx%3==0])
```
%% Output
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
[0, 6, 12, 18]
%% Cell type:markdown id: tags:
Последняя форма в разы удобнее, чем запись:
%% Cell type:code id: tags:
``` python
lst=[]
forxinrange(10):
ifx%3==0:
lst.append(2*x)
print(lst)
```
%% Output
[0, 6, 12, 18]
%% Cell type:markdown id: tags:
### Раздел 2. Типы-множества
Типы данных-множества — типы, для которых доступны оператор вхождения in, функция len и доступ, как к итератору. В Python есть два типа множеств — set и frozenset. Тип frozenset является неизменяемым, поэтому для него недоступны методы для типа set, которые изменяют объект. В остальном они идентичны.
Только хешируемые объекты могут быть добавлены в множество. Все встроенные неизменяемые типы являются хешируемыми.
#### Множества
Множество типа set есть неупорядоченная коллекция из нуля или более ссылок на хешируемые объекты. Множества изменяемы, так что в них можно добавлять и удалять элементы. Будучи неупорядоченными, понятие индекса или позиции для них не имеет смысла.
Для создания множества используется либо вызов set(), который без аргументов создает пустое множество. С аргументом типа set создается поверхностная копия множества, а с другим аргументом выполняется попытка приведения к множеству. Данная функция не принимает более одного аргумента. Множество может быть также создано путем заключения элементов в фигурные скобки, но стоит учитывать, что пустое множество не может быть создано таким образом, так как {} создаст пустой словарь.
Множества поддерживают функцию len(), которое возвращает число элементов множества.
Для типа set доступны следующие методы:
| Метод | Описание |
| ----- | :------- |
| s.add(x) | Добавляет элемент x во множество s, если такого там нет |
| s.clear() | Удаляет все элементы множества s |
| s.copy() | Создает неглубокую копию множества s |
| s.difference(t) | Возвращает новое множество, которое содержит все элементы множества s, которые не входят во множество t. Эквивалент s - t |
| s.differenct_update(t) | Удаляет все элементы t из множества s. Эквивалент s -= t |
| s.discard(x) | Удаляет элемент x из множества s |
| s.intersection(t) | Возвращает новое множество, которое содержит элементы множества s, которые в то же время являются элементами множества t. Эквивалент s & t |
| s.intersection_update(t) | Удаляет из множества s все элементы, которые не входят в t. Эквивалент s &= t |
| s.isdisjoint(t) | Возвращает True, если у множеств s и t нет общих элементов |
| s.issubset(t) | Возвращает True, если s есть подмножество (несобственное) t. Эквивалент s <= t |
| s.issuperset(t) | Возвращает True, если t есть подмножество (несобственное) s. Эквивалент t <= s |
| s.pop() | Удаляет случайный элемент s и возвращает его. Возбуждает исключение KeyError, если множесво пустое |
| s.remove(x) | Удаляет элемент x из множества s. Возбуждает исключение KeyError, если x не входит в s |
| s.symmetric_difference(t) | Возвращает новое множество, которое содержит элементы, которые либо содержатся в s и не содержатся в t, либо содержатся в t и не содержатся в s. Эквивалент s ^ t |
| s.symmetric_difference_update(t) | Записывает в s симметрическую разность s и t. Эквивалент s ^= t |
| s.union(t) | Возвращает новое множество, которое содержит все элементы множеств s и t |
| s.update(t) | Добавляет все элементы множества t во множество s |
Последние два метода эквивалентны s | t и s |= t соответственно.
#### Генераторы множеств
В целом то же, что и для списков, но сам генератор обозначается фигурными скобками:
%% Cell type:code id: tags:
``` python
print({xforxinrange(10)})
print({2*xforxinrange(10)})
print({2*xforxinrange(10)ifx%3==0})
```
%% Output
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
{0, 2, 4, 6, 8, 10, 12, 14, 16, 18}
{0, 18, 12, 6}
%% Cell type:markdown id: tags:
### Раздел 3. Типы-отображения
Типы отображения — наборы пар "ключ - значение". Единственным встроенным типом-отображением является dictionary, который отображает хешируемые объекты на ссылки на другие объекты.
#### Словари
Тип dict (словарь) это упорядоченная коллекция пар "ключ - значение". Раньше dict был неупорядоченным типом, поэтому во избежания ошибок при исполнении кода более старыми интерпретаторами, советую вам придерживаться отношения к словорям как к неупорядоченным последовательностям.
Словари поддерживают оператор вхождения in, функцию len(), и доступ как к итератору. Среди операций сравнения поддерживаются только == и !=.
Как и обычно, тип dict может быть вызван как функция. Если ей не переданы аргументы, то создается пустой словарь. Если передан аргумент с типом-отображением, то создается словарь на основе этого аргумента. Например, если аргумент типа dict, то будет создана его поверхностная копия. Можно также передать аргумент-последовательность, каждый элемент в котором — последовательность из двух элементов: ключа и значения. Также пустой словарь можно создать при помощи конструкции {}, а словарь с элементами — перечислив пары ключ - значение в фигурных скобках через запятую, отделяя ключи от значений двоеточием:
{ключ1 : значение1, ключ2 : значение2}
К тому же доступны генераторы словарей.
Мы можем доступаться к элементам словаря, используя ключ: d[ключ] вернет значение элемента с ключем *ключ*.
Для добавления новых элементов используется оператор присваивания: d[новый\_ключ] = новое\_значение.
Для типа dict доступны следующие методы:
| Метод | Описание |
| ----- | :------- |
| d.clear() | Удаляет все элементы словаря d |
| d.copy() | Возвращает поверхностную копию словаря d |
| d.fromkeys(s, v) | Возвращает словарь, где ключами являются элементы последователности s, а значения равны v или None, если v не указано |
| d.get(k) | Возвращает значение, которое соответствует ключу k или None, если такого нет |
| d.get(k, v) | Возвращает значение, которое соответствует ключу k или v, если такого нет |
| d.items() | Возвращает view (read-only итератор), содержащий пары (ключ, значение) словаря d |
| d.keys() | Возвращает view, содержащий ключи словаря d |
| d.pop(k) | Удаляет элемент, соответствующий ключу k и возвращает его. Если такого нет, то возбуждается исключение KeyError |
| d.pop(k, v) | Удаляет элемент, соответствующий ключу k и возвращает его. Если такого нет, то возвращается значение v |
| d.popitem() | Удаляет из словаря d и возвращает некоторую пару (ключ, значение). Возбуждает исключение KeyError, если d пуст |
| d.setdefault(k, v) | ТТо же, что и d.get(k), но если такого элемента нет, то создается новый со значением None или v, если указано |
| d.values() | Возвращает view всех значений словаря d |
#### Генераторы словарей
Генераторы словарей имеют две уже знакомые нам формы:
[выражение\_ключа : выражение\_значения for ключ, значение in итератор]
[выражение\_ключа : выражение\_значения for ключ, значение in итератор if условие]
%% Cell type:markdown id: tags:
### Раздел 4. Итераторы. Функции и операци для работы с итераторами
Тип данных называется итерируемым, если он может возвращать свои элементы по одному. Технически, любой объект, реализующий метод \_\_iter\_\_() является итерируемым и может предоставить итератор. Итератор — объект, реализуюзий метод \_\_next()\_\_, возвращающий следующее значение и возбуждающий исключение StopIteration, если элементов больше нет.
Для итерируемых объектов доступны следующие функции и операторы:
| Функция или оператор | Описание |
| -------------------- | :------- |
| s + t | Возвращает конкатенацию последовательностей s и t |
| s * n | Возвращает последовательность, которая является результатом повторения последовательности s n раз |
| x in t | Проверяет, есть ли в последовательности i элемент x |
| all(i) | Возвращает True, если все элементы i при приведении к типу bool имеют значение True |
| any(i) | Возвращает True, если один из элементов i при приведении к типу bool имеет значение True |
| enumerate(i, start) | Возвращает последовательность элементов (индекс, значение) для итератора i, начиная с индекса 0 или start, если данный аргумент задан |
| len(x) | Возвращает число элементов в x |
| max(i, key) | Возвращает максимальный элемент в i. Если аргумент key задан, то возвращает элемент, для которого key максимален |
| min(i, key) | Возвращает минимальный элемент в i. Если аргумент key задан, то возвращает элемент, для которого key минимален |
| range(start, stop, step) | Возвращает итератор, содержащий целые числа от start до stop с шагом step. Аргумент start включен в последовательность, а stop — нет |
| reversed(i) | Возвращает итератор, в котором элементы идут в обратном порядке |
| sorted(i, key, reverse) | Возвращает отсортированный по неубыванию итератор. Если задан аргумент key, то сортировка идет по значением key(x) для каждого элемента x. Если reversre указан как True, то сортировка идет по невозрастанию |
| sum(i, start) | Возвращает сумму элементов в итераторе i плюс start. Если start не задан, то принимается равным 0 |
| zip(i1, ..., iN) | Возвращает итератор из кортежей, состоящий из элементов i1, ..., iN. Количество кортежей определяется минимальной длиной i1, ..., iN |
%% Cell type:markdown id: tags:
### Раздел 5. Копирование коллекций
При присваивании объектов будет выполнено присваивание по ссылке:
%% Cell type:code id: tags:
``` python
x=['Nightwing','Robin','Catwoman']
y=x
x[0]='Alfred'
print(y)
```
%% Output
['Alfred', 'Robin', 'Catwoman']
%% Cell type:markdown id: tags:
Для создания поверхностной копии можно использовать оператор среза:
%% Cell type:code id: tags:
``` python
x=['Nightwing','Robin','Catwoman']
y=x[:]
x[0]='Alfred'
print(y)
```
%% Output
['Nightwing', 'Robin', 'Catwoman']
%% Cell type:markdown id: tags:
Но поверхностная копия имеет ограничения, связанные с тем, что при ее создании создаются копии лишь самих элементов. Если они в свою очередь являются ссылками, то мы снова столкнемся с проблемой:
Есть достаточно интересный модуль vedis, который предоставляет доступ к key-value store типа Redis на диске, но при этом API этого доступа совпадает с доступом к словарю.
Решим с использованием модуля vedis [задачу о гипотезе Колатца](https://lambda-it.ru/post/26) и сделаем визуализацию при помощи matplotlib.
Для начала напишем функцию, которая из текущего числа получает следующее в последовательности:
%% Cell type:code id: tags:
``` python
defnext_kolatz(x):
ifx&1:
return3*x+1
returnx>>1
```
%% Cell type:markdown id: tags:
Если число x является нечетным (последний разряд в двоичной системе равен единице), то мы возвращаем 3x + 1. В противном случае, мы делим число на 2 (соответствует сдвигу вправо на один разряд в двоичной системе счисления). Теперь импортируем модуль vedis. При помощи него мы будем хранить длину цепочки для чисел, которые мы уже встречали. Также напишем функцию, которая вычисляет и возвращает длину цепочки для заданного числа x, записывает ее в хранилище, а также записывает в хранилище длины цепочек для всех промежуточных чисел:
%% Cell type:code id: tags:
``` python
defget_kolatz_length(x,storage):
cur=x
try:
returnint(storage.get(cur))
exceptKeyErrorase:
pass
stack=[cur]
whileTrue:
cur=next_kolatz(cur)
try:
length=int(storage.get(cur))
break
exceptKeyErrorase:
pass
stack.append(cur)
foriteminstack[::-1]:
length+=1
storage.set(item,length)
returnint(storage.get(x))
```
%% Cell type:markdown id: tags:
Теперь напишем функцию, которая возвращает число, меньшее заданного, для которого данная цепочка максимальна и длину цепочки:
Теперь остается только инициализировать хранилище и испытать наши функции:
%% Cell type:code id: tags:
``` python
fromvedisimportVedis
db=Vedis('storage.db')
db.set(1,1)
print(get_max_kolatz_length(100000,db))
db.close()
```
%% Output
(77031, 351)
True
%% Cell type:markdown id: tags:
Теперь построим обычный scatter plot при помощи matplotlib:
%% Cell type:code id: tags:
``` python
importmatplotlib.pyplotasplt
db=Vedis('storage.db')
X=range(1,101)
Y=[get_kolatz_length(x,db)forxinX]
db.close()
plt.scatter(X,Y)
plt.title('Визуализация длин цепочек Колатца')
plt.xlabel('Число')
plt.ylabel('Длина цепочки')
plt.show()
```
%% Output
%% Cell type:markdown id: tags:
### Раздел 7. Домашнее задание
Решить задачи после третьей главы Саммерфилда
Загуглить гипотезу Гольдбаха
Загуглить динамическое программирование
Написать функцию, которая принимает в качестве аргумента множество и функцию и при помощи matplotlib изображает график заданной функции на множестве значений. Добавьте несколько дополнительных аргументов: например, возможность сделать одну из осей логарифмической, выбрать разные цветовые схемы, разные типы графиков и т.д.
Решить задачу, которая будет опубликована в субботу