Математический практикум по Питону.
Вводится базовы объекты из Питона (Python): кортеж (touple) и словарь (dict). Ключевые слова: touple, index, count, zip, list, dict, pop, popitem, update, setdefault, keys, items, values.
Это предварительная версия! Любые замечания приветсвуются.
Мы уже ранее его видели. Всякий раз когда выводятся числа в круглых скобках -- это он. Схож со список, но имет свои отличия. Скорее такой тип данных следует считать набором, т.е. фиксированного размера объект. кортеж.
Создание
a = (0, 4) # Создаем кортеж в явном виде.
a
len(a) # Как и у списка -- его длина, т.е. количество элементов в кортеже.
создания кортежа из одного элемента вещь хитрая.
('один элемент') # Это просто строка.
# Нужно так:
('один элемент',) # В конце запятая.
Предполагается, что компоненты будут иметь определеный смысл.
# Можно задать некую структурированную иформацию.
фио = ('Ломоносов', 'Михаил', 'Васильевич')
фио # Фамилия, имя, отчество.
# Можно индексировать. Причем под заданным индексом
фио[1] # будет информация определенного типа.
# В данном случае, имя.
# Можно задать и другие данные.
года = (1711, 1765) # Например, период лет: начало и конец.
person = ( фио, года) # Потом объеденить.
# Можно все задать одним больших выражением.
person2 = ( ('Ги́льберт', 'Дави́д', 'Отто'), (1862, 1943) )
# Смысл кортежа в том, что объекты под фиксированным индексом имеют одинаковую интерпритацию.
print( person[0][1], person[0][0], 'родился в', person[1][0], 'г.')
print( person2[0][1], person2[0][0], 'родился в', person2[1][0], 'г.')
# можно писать общий код:
prnt_bio = lambda pers: print( pers[0][1], pers[0][0], 'родился в', pers[1][0], 'г.')
prnt_bio(person) # Вызов для одного,
prnt_bio(person2) # вызов для другого.
nums = (2, 1, 3, 1, 5, 6)
# Как и в списке подсчитывает количество элементов равных данному.
nums.count(1)
# Аналогично списку. Поиск элемента равному даному.
nums.index(1) # Возвращает индекс первого вхождения.
# Указав во втором аргументе с кого индекса начинать
nums.index(1, 2) # можно найти второе входение.
# Проверяет принадлежность элемента списку.
4 in nums, 3 in nums
# Кортеж постоянен, т.е. неизменяемый.
фио[1] = 'Максим' # Поэтому, присваивать новое значение нельзя.
Как и менять состав нельзя:
# Пытаемся по аналогии со список добавить элемент.
nums.append(8)
del nums[1] # Удалить поле нельзя.
Добавить новое поле
# Попробуем путем добавления списка.
person + ['деревня Мишанинская'] # К кортежу список добавить нельзя.
# Поробуем добавить "кортеж".
person + ('деревня Мишанинская')
('деревня Мишанинская') # Скобки ничего не значят.
# Получится просто строка.
# А теперь уж добавлением кортежа.
person + ('деревня Мишанинская',) # Все дело в запятой.
# А так можно. Мы создали новый набор.
person # ожидаемо не изменился
person_ex = person + ('деревня Мишанинская',) # Сохраним в переменную.
person_ex
# Теперь в поле под индексом 2 город рождения.
person_ex[2]
prnt_bio = lambda pers: print( pers[0][1], pers[0][0], 'родился в', pers[1][0], 'г.', 'в', pers[2])
prnt_bio( person_ex ) # Выведем расширенную информацию.
prnt_bio( person ) # Разумеется не будет работать с кортежом не имеющего данного поля.
# Создадим два списка.
a = [1, 2, 3]
b = ['a', 'b', 'c']
a, b
# Попарно объеденим их соответствующие элементы.
c = zip( a, b ) # Тоже генератор списка.
c
# Сшивает два списка.
d = list( c ) # Элементы которого картеж из элементов исходных список.
d
d[1] # Кортеж из элементов a[1] и b[1]
a[1], b[1]
# Можно сшивать больше одного списка.
e = list( zip( [1,2,3], ['a','b','c'],d))
e
# Тоже будет кортежом.
e[1] # Только больше элементов.
Поэлементное произведение списоков
b = [4,5,6]
c = list( zip(a, b) )
c
# Получаем список произведения двух списков.
list( map( lambda x: x[0] * x[1], c) )
Создание
country = dict() # Созданем словарь.
# Определяем элементы.
country['Россия'] = 'Москва'
country['Франция'] = 'Париж'
country['Италия'] = 'Рим'
# Ключь может иметь разную природу.
country[8] = 10 # Дали соответствие числу.
# Просмотр словаря. Он задан фигурными скобками.
country # Ключ и значение указаны через двоеточее.
# Сами сущности перечислены через запятую.
# Можно и задать словарь таким же способом.
eng2rus = { 'cat':'кошка', 'dog' : 'собака' }
eng2rus
empty = {} # можно и пустой словарь задать.
empty
type( country ), type( eng2rus ), type( empty ) # Выведем тип явно.
empty = dict() # А теперь можно явно и задать.
empty
aa = id( eng2rus )
eng2rus_copy = eng2rus.copy() # Делаем копию по аналогии со списком.
bb = id( eng2rus_copy )
eng2rus_copy, aa == bb # Словарь скопирован, и сам объект новый.
b = id(eng2rus_copy)
eng2rus_copy.clear() # Очищаем словарь.
a = id(eng2rus_copy)
eng2rus_copy, a == b # Словарь очищен, а объект сохранился.
"Индексация" или как извлечь значение
# Обобщается понятие индекса. Он тепер нетолько числовой.
country['Франция'] # В квадратных скобках указывется ключ.
0 in country # Проверка нахождения ключа в словаре.
# Если ключа нет в словаре, то выдается ошибка.
country['Германия']
Можно более безопасно извлекать. Так, чтобы не обрабатывать в яном виде отсутствие ключа.
# Можно попытатся извлечь и в случае отсутсвия ключа
cap = country.get('Германия', 'информации нет')
cap # вернуть значение по умолчанию.
# Можно вообще не указать и значения по умолчанию.
cap = country.get('Германия')
cap, type(cap) # Специальное значение и тип.
country # Значение для ключа используемого в get не появилось.
# Но значение тем не менее можно задать.
country['Германия'] = 'Берлин'
country # Ранее в словаре его не было. Теперь есть.
# Один словарь обновляет исходный.
country.update({'Россия' : 'Питербург', 'США' : 'Вашингтон'})
country # В исходном обновляются значения (Россия) и добавляются новые (США).
# В отличие от get, setdefault присваивает новое зачение,
q = country.setdefault('Канада', 'Оттава') # если его нет в словаре.
q # Как и с get, setdefault возвращает значение даже, если его нет в словаре.
# Значение (Оттава) для нового ключа (Канада) появилось в словаре.
country
# Но, если в словаре ключ есть, то setdefault, в отличие от присвоения,
cap = country.setdefault('Россия', 'Москва') # старое значение не обновляет.
cap # А также, возвращает текущее значение ключа.
country # Значение не обновилось.
country['Россия'] = 'Москва' # а так обновим.
country
Обработка
# Можно извлечь конкретный элемент.
country.pop('Франция')
country # Франции больше в словаре нет.
# Извлекаем сразу одну сущность (случайно,
elem = country.popitem() # на порядок рассчитывать не стоит).
elem # Кортеж из ключа и значения.
country
f'Кортеж состоящий из ключа, {elem[0]}, и значения, {elem[1]}.'
Обработка списком
Как обрабатывать элементы словаря. Например, мы хотим найти элемент словаря с определенным свойстом или что-то со всеми ими сделать.
# Преобразование словаря в список.
cc = list( country ) # Останутся только ключи. Значения пропадут.
cc
list( map( print, cc) ) # Например вывести название стран.
# Последнее эквивалентно явному вызову метода keys.
dd = list( country.keys() )
dd # Можно узнать какие ключи есть.
# Но никто не запрещает "вспомнить" значения.
list( map( lambda x:print('столицей', x, 'является', country[x]), cc) )
# Используем словарь для вывода значений.
# А можно и сразу получить доступ к ключю и его значению.
ii = list( country.items() )
ii
# Тогда можно так.
list( map( lambda x:print('столицей', x[0], 'является', x[1]), ii) )
country.values() # Данный метод наоборот возвращает значения.
stud = dict({'Максим' : 'Россия', 'Аннетт' : 'Франция', 'Дима' : 'Россия', 'Луиза' : 'Франция'})
stud # Словарь оторажает имя на страну из которой приехал студент.
stud.values() # Страны из которых приехали студенты.
countries = list(stud.values())
countries # Список стран.
# Благодаря славарю получили список стран без повторов.
dict.fromkeys(countries) # Хак..
ii
Построим словарь в обратную сторону.
rr=dict()
# Попробуем так.
list(map( lambda i: rr[i[1]] = rr[i[0]], ii))
# Но будет ошибка.
Нельзя присваивать в ламбда операторе. Предполагается, что ламбда оператор действует как функция: на вход значение, на выход значение. Ничего присваивать нельзя.
если нельзя, но очень хочется, то можно
# Вызовем метод словаря. setdefault позволяет менять значение.
list(map( lambda i: rr.setdefault(i[1],i[0]), ii))
# Ошибки не будет.
rr
Сложный ключ
Наборы могут выступать в качестве ключа/индекса у словаря.
name = ['Ломоносов', 'Михаил', 'Васильевич']
name
advisor = ['Вольф', 'Христиан фон', '?']
advisor
# Хотим создать словарь в котором по ключу можно узнать научного руководителя.
advisors = dict()
advisors[name] = advisor # Система выдаст ошибку.
# По сути по причине того, что список мы знаем как изменяемый объект.
name = ('Ломоносов', 'Михаил', 'Васильевич')
advisor = ('Вольф', 'Христиан фон', '?')
name, advisor
# Теперь разрешено добавить запись в словарь.
advisors[name] = advisor
advisors # Видим что изменение что надо.
f'Научным руководителем {name} является {advisors[name]}.'