# Отчет по Теме 3

Турханов Артем, А-03-23

## 1 Преобразование простых базовых типов
### 1.1 Преобразование в логический тип
```py
>>> logiz1=bool(56); logiz1; type(logiz1)
True
<class 'bool'>
>>> logiz2=bool(0); logiz2; type(logiz2)
False
<class 'bool'>
>>> logiz3=bool('Beta'); logiz3; type(logiz3)
True
<class 'bool'>
>>> logiz4=bool(''); logiz4; type(logiz4)
False
<class 'bool'>
```
### 1.2 Преобразование в целочисленный тип
```py
>>> tt1=int(198.6); tt1
198
>>> tt2=int("-76"); tt2
-76
>>> tt3=int("B",16); tt3
11
>>> tt4=int("71",8); tt4
57
```
Если же попробуем передать строку, содержащую число с точкой, то получим ошибку:
```py
>>> tt5=int("98.76"); tt5
Traceback (most recent call last):
  File "<pyshell#9>", line 1, in <module>
    tt5=int("98.76"); tt5
ValueError: invalid literal for int() with base 10: '98.76'
```
Это происходит потому, что int() может принимать только строки, содержащие целые числа. Функция не может конверитровать строку, содержащую число с точкой. 

### 1.3 Преобразование в вещественный тип
```py
>>> flt1=float(789); flt1
789.0
>>> flt2=float(-6.78e2); flt2
-678.0
>>> flt3=float("Infinity"); flt3
inf
>>> flt4=float("-inf"); flt4
-inf
```
### 1.4 Преобразование в другие системы счисления

```py
>>> hh=123
>>> dv1=bin(hh); dv1
'0b1111011'
>>> vos1=oct(hh); vos1
'0o173'
>>> shs1=hex(hh); shs1
'0x7b'
```
Выполним обратное преобразование для проверки полученных результатов:
```py
>>> int(dv1,2)
123
>>> int(vos1,8)
123
>>> int(shs1,16)
123
```
## 2 Преобразование более сложных базовых типов
### 2.1 Преобразование в строку символов
```py
>>> strk1=str(23.6); strk1
'23.6'
>>> strk2=str(logiz3); logiz3; strk2
True
'True'
>>> strk3=str(["A","B","C"]); strk3
"['A', 'B', 'C']"
>>> strk4=str(("A","B","C")); strk4
"('A', 'B', 'C')"
>>> strk5=str({"A":1,"B":2,"C":9}); strk5
"{'A': 1, 'B': 2, 'C': 9}"
```
### 2.2 Преобразование элементов объекта в список
```py
>>> spis1=list("Строка символов"); spis1
['С', 'т', 'р', 'о', 'к', 'а', ' ', 'с', 'и', 'м', 'в', 'о', 'л', 'о', 'в']
>>> spis2=list((124,236,-15,908)); spis2
[124, 236, -15, 908]
>>> spis3=list({"A":1,"B":2,"C":9}); spis3
['A', 'B', 'C']
```
Заметим, что из словаря в список попали только ключи. Чтобы в список смогли попасть не ключи, а значения словаря, можно выполнить следующую инструкцию:
```py
>>> spis4=list({"A":1,"B":2,"C":9}.values()); spis4
[1, 2, 9]
```
### 2.3 Преобразование элементов объектов в кортеж
```py
>>> kort7=tuple('Строка символов'); kort7
('С', 'т', 'р', 'о', 'к', 'а', ' ', 'с', 'и', 'м', 'в', 'о', 'л', 'о', 'в')
>>> kort8=tuple(spis2); spis2; kort8
[124, 236, -15, 908]
(124, 236, -15, 908)
>>> kort9=tuple({"A":1,"B":2,"C":9}); kort9
('A', 'B', 'C')
```
### 2.4 Удаление объектов
```py
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'dv1', 'flt1', 'flt2', 'flt3', 'flt4', 'hh', 'kort7', 'kort8', 'kort9', 'logiz1', 'logiz2', 'logiz3', 'logiz4', 'shs1', 'spis1', 'spis2', 'spis3', 'spis4', 'strk1', 'strk2', 'strk3', 'strk4', 'strk5', 'tt1', 'tt2', 'tt3', 'tt4', 'vos1']
>>> del strk5, kort8
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'dv1', 'flt1', 'flt2', 'flt3', 'flt4', 'hh', 'kort7', 'kort9', 'logiz1', 'logiz2', 'logiz3', 'logiz4', 'shs1', 'spis1', 'spis2', 'spis3', 'spis4', 'strk1', 'strk2', 'strk3', 'strk4', 'tt1', 'tt2', 'tt3', 'tt4', 'vos1']
>>> my_name = 'Turkhanov A.K.'
>>> spis = list(my_name);spis
['T', 'u', 'r', 'k', 'h', 'a', 'n', 'o', 'v', ' ', 'A', '.', 'K', '.']
>>> tp = tuple(spis); tp
('T', 'u', 'r', 'k', 'h', 'a', 'n', 'o', 'v', ' ', 'A', '.', 'K', '.')
>>> s = str(tp); s
"('T', 'u', 'r', 'k', 'h', 'a', 'n', 'o', 'v', ' ', 'A', '.', 'K', '.')"
```
## 3 Арифметические операции
### 3.1 Сложение и вычитание
```py
>>> 12+7+90
109
>>> 5.689e-1 - 0.456
0.11289999999999994
>>> 23.6+54
77.6
>>> 14-56.7+89
46.3
```
### 3.2 Умножение
```py
>>> -6.7*12
-80.4
```
### 3.3 Деление
```py
>>> -234.5/6
-39.083333333333336
>>> a=178/45; a; type(a)
3.9555555555555557
```
### 3.4 Деление нацело
```py
<class 'float'>
>>> b=178//45; b; type(b)
3
<class 'int'>
>>> c=-24.6//12.1; c; type(c)
-3.0
<class 'float'>
>>> d = 178//-24.6; d; type(d)
-8.0
<class 'float'>
>>> e = -24.6//45; e; type(e)
-1.0
<class 'float'>
```
### 3.5 Остаток от деления
```py
>>> 148%33
16
>>> 12.6%3.8
1.2000000000000002
>>> x = 148%3.8; x; type(x)
3.6000000000000068
<class 'float'>
>>> y = 12.6%5; y; type(y)
2.5999999999999996
<class 'float'>
```
### 3.6 Возведение в степень
```py
>>> 14**3
2744
>>> e=2.7**3.6; e
35.719843790663525
>>> x = 14**3.2
>>> x
4651.678749230765
>>> y = 2.7**3; y
19.683000000000003
```
### 3.7 Арифметические операции с комплексными числами
```py
>>> z1 = 1 + 2j; z2 = 2 - 1j
>>> z1 + z2
(3+1j)
>>> z1 - z2
(-1+3j)
>>> z1*z2
(4+3j)
>>> 2*z1
(2+4j)
>>> 2.8*z2
(5.6-2.8j)
>>> z1/z2
1j
>>> z1/3.8
(0.2631578947368421+0.5263157894736842j)
>>> z2/3
(0.6666666666666666-0.3333333333333333j)
>>> z1//3.8; z1//3
Traceback (most recent call last):
  File "<pyshell#30>", line 1, in <module>
    z1//3.8; z1//3
TypeError: unsupported operand type(s) for //: 'complex' and 'float'
>>> z1 // 4
Traceback (most recent call last):
  File "<pyshell#31>", line 1, in <module>
    z1 // 4
TypeError: unsupported operand type(s) for //: 'complex' and 'int'
>>> z1 % 2
Traceback (most recent call last):
  File "<pyshell#32>", line 1, in <module>
    z1 % 2
TypeError: unsupported operand type(s) for %: 'complex' and 'int'
>>> z1**3
(-11-2j)
>>> z2**z1
(2.3304790489341802+5.149201131069769j)
```
Можно заметить, что с комплексными числами невозможно выполнить операции деления нацело и взятие остатка от деления.

## 4 Операции с двоичными числами
### 4.1 Двоичная инверсия
```py
>>> dv1=9; bin(dv1)
'0b1001'
>>> dv2 = ~dv1; dv2; bin(dv2);
-10
'-0b1010' # Не соответсвует тому, как Python представляет отрицательные целые числа
```
Получиили число -10. Дело в том, что в Python целые числа представляются в "дополнительном коде". Например у нас есть 8-битное целое число. Пусть это будет число 9, как в примере выше. Его доичное представление: 00001001. Инвертируя каждый бит с помощью операции двоичный инверсии ~, получаем: 11110110. И до, и после инверсии битов двоичное представление числа - это представление в дополнительном коде. В силу способа перевода прямого кода в дополнительный, заметим, что инверсное число 9, то есть 11110110 в двоичном предаствлении, - это не что иное, как целое число -10. Докажем это:
число -10 получается из числа 10. В двоичном представлении 10 - это: 00001010. Инверсируя каждый бит, получаем: 11110101. Прибавляем единицу: 11110101 + 1 = 11110110. Ч.т.д.
### 4.2 Двоичное "И"
```py
>>> a = 7&9; bin(7), bin(9), bin(a)
('0b111', '0b1001', '0b1')
>>> a = 7&8; bin(7), bin(8), bin(a)
('0b111', '0b1000', '0b0')
```
### 4.3 Двоичное "ИЛИ"
```py
>>> a = 7|9; bin(7), bin(9), bin(a)
('0b111', '0b1001', '0b1111')
>>> a = 7|8; bin(7), bin(8), bin(a)
('0b111', '0b1000', '0b1111')
>>> a = 14|5; bin(14), bin(5), bin(a)
('0b1110', '0b101', '0b1111')
```
### 4.4 Двоичное "исключающее ИЛИ"
```py
>>> a = 14^5; bin(14), bin(5), bin(a); a
('0b1110', '0b101', '0b1011')
11
```
### 4.3 Побитовый сдвиг
```py
>>> h=14; bin(h)
'0b1110'
>>> g=h<<2; bin(g)
'0b111000'
>>> g1=h>>1; bin(g1)
'0b111'
>>> g2=h>>2; bin(g2)
'0b11'
```
И другие примеры двоичных операций:
```py
>>> a = 120; b = 125; bin(120); bin(125)
'0b1111000'
'0b1111101'
>>> ~a; ~b
-121
-126
>>> a&b; bin(a&b)
120
'0b1111000'
>>> a|b; bin(a|b)
125
'0b1111101'
>>> a^b; bin(a^b)
5
'0b101'
>>> bin(a); bin(a<<2)
'0b1111000'
'0b111100000'
>>> bin(b); bin(b>>1)
'0b1111101'
'0b111110'
```
## 5 Операции при работе с последовательностями (строками, списками, кортежами)
### 5.1 Конкатенация
```py
>>> 'Система '+'регулирования'
'Система регулирования'
>>> ['abc','de','fg']+['hi','jkl']
['abc', 'de', 'fg', 'hi', 'jkl']
>>> ('abc','de','fg')+('hi','jkl')
('abc', 'de', 'fg', 'hi', 'jkl')
```
### 5.2 Повторение
```py
>>> 'ля-'*5
'ля-ля-ля-ля-ля-'
>>> ['ку','-']*3
['ку', '-', 'ку', '-', 'ку', '-']
>>> ('кис','-')*4
('кис', '-', 'кис', '-', 'кис', '-', 'кис', '-')
>>> signal1=[0]*3+[1]*99; signal1
[0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
>>> signal2=(0,)*3+(1,)*5+(0,)*7; signal2
(0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0)
```
### 5.3 Проверка наличия заданного элемента в последовательности
```py
>>> stroka='Система автоматического управления'
>>> 'автомат' in stroka
True
>>> 'ку' in ['ку','-']*3
True
>>> 'ля-' in ('abc', 'de', 'fg', 'hi', 'jkl')
False
```
### 5.4 Подстановка значений в строку
```py
>>> stroka='Температура = %g %s  %g'
>>> stroka % (16,' меньше ',25)
'Температура = 16  меньше   25'
>>> stroka='Температура = %(zn1)g %(sravn)s  %(zn2)g'
>>> stroka % {'zn1':16,'sravn':' меньше ','zn2':25}
'Температура = 16  меньше   25'
```
## 6 Присваивание
### 6.1 Присваивание значения переменной
```py
>>> zz=-12; zz
-12
```
### 6.2 Увеличение (уменьшение) на заданную величину
```py
>>> zz+=5; zz
-7
>>> zz-=3; zz
-10
>>> stroka='Система'
>>> stroka+=' регулирования'
>>> stroka
'Система регулирования'
```
### 6.3 Умножение (деление) на заданную величину
```py
>>> zz; zz/=2; zz
-10
-5.0
>>> zz*=5; zz
-25.0
>>> stroka='Повтор '
>>> stroka *= 3; stroka
'Повтор Повтор Повтор '
```
### 6.4 Деление с округлением вниз, получение остатка от деление и возведение в степень
```py
>>> a = 35; a //= 3; a
11
>>> a = 35; a %= 3; a
2
```
### 6.5 Множественное присваивание
```py
>>> w=v=10; w; v
10
10
>>> n1,n2,n3=(11,-3,'all')
>>> n1; n2; n3
11
-3
'all'
>>> n1,n2,n3='1,2,3'
Traceback (most recent call last):
  File "<pyshell#77>", line 1, in <module>
    n1,n2,n3='1,2,3'
ValueError: too many values to unpack (expected 3)
>>> n1,n2,n3=[1,2,3]
>>> n1; n2; n3
1
2
3
>>> n1,n2=[1,2,3]; n1; n2
Traceback (most recent call last):
  File "<pyshell#80>", line 1, in <module>
    n1,n2=[1,2,3]; n1; n2
ValueError: too many values to unpack (expected 2)
>>> n1,n2,n3={1,2,3}
>>> n1; n2; n3
1
2
3
>>> n1,n2={1,2,3}; n1; n2
Traceback (most recent call last):
  File "<pyshell#83>", line 1, in <module>
    n1,n2={1,2,3}; n1; n2
ValueError: too many values to unpack (expected 2)
```
Заметим, что при множественном присваивании нельзя использовать строку. Кортеж, список и множество использовать можно. Но важно, чтобы количество переменных, которым присваиваются значения, было равно количество элементов кортежа, списка или множества.
## 7 Логические операции
### 7.1 Сравнение
```py
>>> w; v
10
10
>>> w == v
True
>>> w != v
False
>>> 1 != 2
True
>>> 3 < 10
True
>>> 10 > 5
True
>>> 3 <= 3; 5>= 3; 7>= 7
True
True
True
```
### 7.2 Проверка наличия
```py
>>> mnoz1={'pen','book','pen','iPhone','table','book'}
>>> 'book' in mnoz1; 'cap' in mnoz1
True
False
>>> dic1={'Saratov':145, 'Orel':56, 'Vologda':45}
>>> 'Vologda' in dic1; 'Pskov' in dic1; 56 in dic1.values();
True
False
True
>>> dct1={'Institut':['AVTI','IEE','IBB'],'Depart':['UII','PM','VMSS','MM'],'gruppa': ['A-01-15','A-02-15']}
>>> 'UII' in dct1['Depart']
True
>>> dct1['Depart'][1] == 'MM'
False
```
### 7.3 Логические выражения
```py
>>> a=17; b=-6
>>> (a>=b) and ('book' in mnoz1) and not ('Pskov' in dic1)
True
>>> (b<a) and not('UII' in dct1['Institut'])
True
>>> 'VMSS' in dct1['Depart'] or not(b != 0)
True
```
### 7.4 Проверка ссылок переменных на один и тот же объект
```py
>>> w=v=10
>>> w is v
True
>>> w1=['A','B']; v1=['A','B']
>>> w1 is v1
False
```
В случае использования операции множественного присваивания все переменные будут ссылаться на один и тот же объект (одну и ту же ячейку) оперативной памяти. Если же двум различным переменным (не при множественном присваивании, а отдельно) присвоено одно и то же значение, то они, переменные, будут ссылаться на разные объекты оперативной памяти. Потому и операция w1 is v1 выдаст FALSE.
## 8 Методы
```py
>>> stroka='Микропроцессорная система управления'
>>> dir(stroka)
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
```
### 8.1 Методы для работы со строками
```py
>>> stroka.find('пр')
5
>>> stroka.count("с")
4
>>> stroka.replace(' у',' автоматического у')
'Микропроцессорная система автоматического управления'
>>> spis22=stroka.split(' ')
>>> spis22
['Микропроцессорная', 'система', 'управления']
>>> stroka.upper()
'МИКРОПРОЦЕССОРНАЯ СИСТЕМА УПРАВЛЕНИЯ'
>>> stroka3=" ".join(spis22); stroka3
'Микропроцессорная система управления'
>>> stroka3.partition("с")
('Микропроце', 'с', 'сорная система управления')
>>> stroka3.rpartition("с")
('Микропроцессорная си', 'с', 'тема управления')
>>> strk1='Момент времени {}, значение = {}'
>>> strk1.format(1,89.7); strk1
'Момент времени 1, значение = 89.7'
'Момент времени {}, значение = {}'
>>> strk2='Момент времени {1}, значение = {0}:{2}'
>>> strk2.format(36.7,2,'норма!')
'Момент времени 2, значение = 36.7:норма!'
>>> strk3='Момент времени {num}, значение = {znch}'
>>> strk3.format(znch=89.7,num=2)
'Момент времени 2, значение = 89.7'
```
### 8.2 Методы для работы со списками
```py
>>> spsk = [1, 'два', 3.0, True, 5j]
>>> dir(spsk)
['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>> spsk.pop(2)
3.0
>>> spsk
[1, 'два', True, 5j]
>>> spsk.append('c'); spsk
[1, 'два', True, 5j, 'c']
>>> spsk.insert(2,'a'); spsk
[1, 'два', 'a', True, 5j, 'c']
>>> spsk.count('a')
1
>>> spsk
[1, 'два', 'a', True, 5j, 'c']
```
Операциия spsk.pop(2) "вытягивает" (от агнл. pop - выпригивать) из списка spsk элемент с индексом 2, т.е. третий элемент. При этот элемент удаляется из списка. То есть метод (функция) pop(i) удаляет элемент списка под индексом i и возвращает его (удаленного элемента) значение. 

Операция spsk.append('c') добавляет в конец списка spsk элемент 'c'.

Операция spsk.insert(2, 'a') вставляет на место второго индекса элемент 'a'.

Операция spsk.count('a') возвращает количество элементов 'a' в списке spsk.
### 8.3 Методы для работы с кортежами
```py
>>> t1 = (1, 'два', 3.0, True, 5j)
>>> dir(t1)
['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
>>> t1.count('a')
0
>>> t1.count(1)
2
>>> t1.index('два'); t1.index(1)
1
0
```
Метод count аналогичен одноименному методу списков: возвращает колчество элементов, соответствующих элементу, переданному в качестве аргумента фунции count().

Метод index возвращает первое вхождение (инедкс первого вхождения) элемента, указанного в качестве аргумента функции index().
### 8.4 Методы для работы со словарями
```py
>>> d1 = {'name': 'Artem', 'age': 20, 'institute':'MPEI'}
>>> dir(d1)
['__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__ior__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__ror__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
>>> d2 = d1.copy(); d2
{'name': 'Artem', 'age': 20, 'institute': 'MPEI'}
>>> d3 = d1; d3
{'name': 'Artem', 'age': 20, 'institute': 'MPEI'}
>>> d3 is d1
True
>>> d2 is d1
False
>>> d2['name'] = 'Ivan'; d2; d1
{'name': 'Ivan', 'age': 20, 'institute': 'MPEI'}
{'name': 'Artem', 'age': 20, 'institute': 'MPEI'}
>>> d3['name'] = 'Jacob'; d3; d1
{'name': 'Jacob', 'age': 20, 'institute': 'MPEI'}
{'name': 'Jacob', 'age': 20, 'institute': 'MPEI'}
```
Метод copy создает неглубоекую копю словаря, переданного как аргумент функции copy(). В нашем случае d2 - неглубокая копия словая d1, а d3 - просто копия словаря d1. Это можно показать с помощью оператора is. Операция d3 is d1 дает True. Это значит, что d3 и d1 ссылаются на один и тот же элемент (ячейку) оперативной памяти ПК, и изменения d3 повлечет за собой изменения и d1 и наоборот. В случае же неглубокой копии d2 создаетяся новая ячейка оперативной памяти, куда копируется содержимое ячейки памяти элементов d1. Т.е. в таком случае словари d2 и d1 никак между собой не связаны. Они указывают на разные ячейки памяти ПК. Это можно увидеть, выполнив операцию d2 is d1, которая вернет False. Поэтому изменение элементов словаря d2 никак не повлияет на изменение словаря d1.

```py
>>> help(d1.get)
Help on built-in function get:

get(key, default=None, /) method of builtins.dict instance
    Return the value for key if key is in the dictionary, else default.

>>> d1.get('name'); d1.get('surname')
'Jacob'
```
Метод get дает возможность получить значение по ключу.
```py
>>> d1.items()
dict_items([('name', 'Jacob'), ('age', 20), ('institute', 'MPEI')])
```
Метод items дает возможность посмотреть все элементы (ключи и значения) словаря.
```py
>>> d1.values()
dict_values(['Jacob', 20, 'MPEI'])
```
Метод values дает возможность посмотреть все значения, хранящиеся в словаре, без ключей.
```py
>>> d1.keys()
dict_keys(['name', 'age', 'institute'])
```
Метод keys дает возможность посмотреть все ключи, имеющиеся в словаре, без соответствующих им значений.
```py
>>> help(d1.pop)
Help on built-in function pop:

pop(key, default=<unrepresentable>, /) method of builtins.dict instance
    D.pop(k[,d]) -> v, remove specified key and return the corresponding value.

    If the key is not found, return the default if given; otherwise,
    raise a KeyError.

>>> d1.pop('name'); d1
'Jacob'
{'age': 20, 'institute': 'MPEI'}
```
Метод pop дает возможность "вырвать" элемент из словаря: получить значение по заданному ключи. При этом элемент, значение которго было получено с помощью pop() по его ключу, будет удален из словаря.
```py
>>> d1['name'] = 'Artem'; d1
{'age': 20, 'institute': 'MPEI', 'name': 'Artem'}
>>> name = ('John', 'Alex', 'Kate')
>>> age = 20
>>> d4 = dict.fromkeys(name, age); d4
{'John': 20, 'Alex': 20, 'Kate': 20}
```
Метод fromkeys дает возможность содать словарь по заданной последовательности ключей, присвоив им значение None (по умолчанию) или же то значение, которое мы сами зададим.
```py
>>> d1.popitem(); d1
('name', 'Artem')
{'age': 20, 'institute': 'MPEI'}
>>> d1.popitem(); d1
('institute', 'MPEI')
{'age': 20}
```
Метод popitem дает возможность выбрать, "выдернуть" элемент из словаря. Функция popitem не принимает никаких аргументов. Она выбирает элемент словаря по принципу LIFO. При выборке элемента, он (элемент) удаляется из словаря.
```py
>>> d1 = {'name': 'Artem', 'age': 20, 'institute':'MPEI'}
>>> d5 = {'name': 'Artemiy', 'surname': 'Turkhanov'}
>>> d1.update(d5, city = 'Moscow'); d1
{'name': 'Artemiy', 'age': 20, 'institute': 'MPEI', 'surname': 'Turkhanov', 'city': 'Moscow'}
>>> d1
{'name': 'Artem', 'age': 20, 'institute': 'MPEI'}
>>> d5 = {'name': 'Artemiy', 'surname': 'Turkhanov'}
>>> d1.update(d5, city = 'Moscow'); d1
{'name': 'Artemiy', 'age': 20, 'institute': 'MPEI', 'surname': 'Turkhanov', 'city': 'Moscow'}
```
Метод update дает возможность обновлять словарь: добавлять новые элементы, изменять имеющиеся разными способами.
```py
>>> d1.setdefault('city'); d1
'Moscow'
{'name': 'Artemiy', 'age': 20, 'institute': 'MPEI', 'surname': 'Turkhanov', 'city': 'Moscow'}
>>> d1.setdefault('country'); d1
{'name': 'Artemiy', 'age': 20, 'institute': 'MPEI', 'surname': 'Turkhanov', 'city': 'Moscow', 'country': None}
>>> d1.setdefault('gender', 'male'); d1
'male'
{'name': 'Artemiy', 'age': 20, 'institute': 'MPEI', 'surname': 'Turkhanov', 'city': 'Moscow', 'country': None, 'gender': 'male'}
```
Метод setdefault дает возможность получить значение элемента словаря по заданному ключу, а если такого ключа не существует в данном словаре, то создает новый элемент с заданным ключом и значением по умполчанию, а также возвращает указанное значение по умолчанию (если не находит элемента с заданным ключом).
```py
>>> d1.clear(); d1
{}
```
Метод clear дает возможность очистить словарь от всех его элементов.
### 8.5 Методы для работы с множествами
```py
>>> s1 = set([1, 'два', 3.0, True, 5j])
>>> s1
{1, 3.0, 5j, 'два'}
>>> dir(s1)
['__and__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__iand__', '__init__', '__init_subclass__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']
>>> s1.add(2); s1
{1, 2, 3.0, 5j, 'два'}
>>> s1.add(1); s1
{1, 2, 3.0, 5j, 'два'}
```
Метод add дает возможность добавлять уникальные элементы в множество.
```py
>>> s1 = {'a', 'b', 'c'}; s2 = {'d', 'a', 'f'}
>>> s1.difference(s2); s2.difference(s1)
{'b', 'c'}
{'f', 'd'}
>>> s1.difference_update(s2)
>>> s1
{'c', 'b'}
```
Методы difference и difference_update позволяют получить разность множеств, т.е. понять, какие элементы есть только в первом множестве. Однако первый метод возвращает новое множество, а второй - изменяет первое множество на "разность".
```py
>>> s1.discard('a')
>>> s1
{'c', 'b'}
>>> s1.remove('a')
Traceback (most recent call last):
  File "<pyshell#87>", line 1, in <module>
    s1.remove('a')
KeyError: 'a'
>>> s1.discard('c'); s1
{'b'}
>>> s1.remove('b'); s1
set()
```
Методы discard и remove тоже похожи между собой. И тот, и другой удаляют элемент из множества. Только remove, если не найдет указанный элемент, который мы хотим удалить, выдаст ошибку KeyError, когда discard никакой ошибки не выдает, если не находит нужного эемента.
```py
>>> s2
{'a', 'f', 'd'}
>>> s1 = {'a', 'f', 'c'}
>>> s1.intersection(s2); s2.intersection(s1)
{'a', 'f'}
{'a', 'f'}
>>> s1.intersection_update(s2); s1
{'a', 'f'}
```
Методы intersection и intersection_update также очень похоже. Это методы выделения пересечения множеств, т.е. нахождения общих элементов двух множеств и создания из них нового множества. Только первый метод не изменяет исходного множества (первого), а просто возвращает пересечение, когда как второй метод изменяет: присваивает первому множеству значения множества, полученног путем пересечения двух сравниваемых множеств.
```py
>>> s2
{'a', 'f', 'd'}
>>> s1.isdisjoint(s2); s2.isdisjoint(s1)
False
False
```
Метод isdisjoint дает возможность проверить: являются ли множества перечекающимися. Если первое множества пересекаются, то функция isdisjoin() выдаст False, если же нет - True.
```py
>>> s1.issubset(s2); s2.issubset(s1)
True
False
>>> s1.issuperset(s2); s2.issuperset(s1)
False
True
```
Методы issubset и issuperset очень похожи. До противоположности. issubset позволяет понять, является ли первое множество подмножеством второго, или нет. А issuperset - является ли первое множество надмножеством второго. 
```py
>>> s1; s2
{'a', 'f'}
{'a', 'f', 'd'}
>>> s1.add('c')
>>> s1.symmetric_difference(s2); s2.symmetric_difference(s1)
{'c', 'd'}
{'d', 'c'}
>>> s1.symmetric_difference_update(s2); s1
{'d', 'c'}
```
Методы symmetric_difference и symmetric_difference_update очень похожи. И тот, и другой создают новое множество, которое является склейкой элементов, которые не принадлежат пересечению двух данных множеств. Только первый метод просто возвращает новое множество, а второй - изменяет первое множество на новое.
```py
>>> s1.union(s2)
{'f', 'd', 'a', 'c'}
```
Метод union объединяет два множества.
```py
>>> s1.update([1,2,3]); s1
{1, 2, 3, 'd', 'c'}
>>> s2.update((1,2,3))
>>> s2
{1, 2, 3, 'a', 'f', 'd'}
>>> s1.update('Hello!')
>>> s1
{1, 2, 3, 'e', 'o', 'H', 'd', '!', 'l', 'c'}
```
Метод update позволяяет обновлять множество: добавлять в него новые элементы, используя в качестве аргумента функции update() дюбой итерируемый объект (список, кортеж или строку).

Также у множеств есть еще методы pop и clear, действия которых аналогичны одноименным методам словарей, которые были рассмотрены в п. 8.4 "Методы для работы со словарями".