Справочник по Python. Часть 2

Типы данных в Python (продолжение)

В этой части мы продолжим изучать типы данных языка программирования Python, научимся хранить некоторое количество информации в одном объекте, изучим функции и работу с файлами.


Структуры данных. Хранение некоторого количества информации.


Списки

Список – это тип данных, позволяющий хранить несколько элементов одного или раз-ных типов данных. В программировании списки часто называют массивами.
В списке каждый элемент имеет индекс (порядковый номер). Индексация начинается с 0.

Чтобы создать список, нужно открыть и закрыть квадратные скобки:

A = []
B = list()

В примере к переменным A и B присваиваются пустые списки.

Чтобы заполнить список, достаточно прописать элементы в скобках через запятую:

B = [1, True, “Python”, 3.14]

Получить элемент списка можно, указав название списка и индекс в квадратных скобках:

B = [1, True, “Python”, 3.14] Вывод: 1
print(B[0])

Таблица индексов
Индекс справа налево 0 1 2
Элементы списка         1 True “Python”
Индекс слева направо -3 -2 -1

Полный список можно вывести с помощью функции print():
A = [1, True, “Python”, 3.14] Вывод: [1, True, “Python”, 3.14]


Функция list()

Функция list() создаёт пустой список, а также приводит некоторые типы данных к типу «список». Рассмотрим действие функции:

NoneList = list() Вывод:
numbers = list(range(0, 6, 2)) []
chars = list(‘abcde’) [0, 2, 4]
print(NoneList) [‘a’, ‘b’, ‘c’, ‘d’, ‘e’]
print(numbers)
print(chars)


Списковые выражения

Списковые выражения позволяют создать список из значений, перебираемых в цикле.

Например:
Вывод:
numbers = [i for i in range(5)] [0, 1, 2, 3, 4]
print(numbers)


Работа со списками

Как и над строками, над массивами можно совершать действия. Массивам присуще следующее:

• Функция len()
• Оператор in
• Индексация
• Срезы
• Конкатенация
• Умножение на целое число
• Функции min() и max()


Функция len()

Функция len() возвращает длину списка.

a = [0,1,2,3,4] Вывод:
print(len(a)) 5


Оператор in

Оператор in отвечает на вопрос: «Есть ли элемент в списке?»
a = [0,1,2,3,4] Вывод:
print(0 in a) True
print(5 not in a) True
print(6 in a) False


Срезы

Срез – это часть списка. Работают срезы также, как и у строк:

a = [0,1,2,3,4] Вывод:
print(a[0:4:2]) [0, 2, 4]


Конкатенация

Конкатенация списков – это образование нового списка, путём сложения исходных:
a = [1, 2] Вывод:
b = [“Python”, True] [1, 2, True, “Python”]
print(a + b)


Умножение на целое число

Умножение на целое число – это образование нового списка, путём повтора исходного списка некоторое количество раз:

b = [“Python”, True] Вывод:
print(b*3) [“Python”, True, “Python”, True, “Python”, True]


Функция sum()

Функция sum(list) возвращает сумму элементов списка, если данное возможно.
list = [1, 2, 3] Вывод:
summ=sum(list) 6
print(summ)


Функции min(), max()

Функция min() возвращает минимальное значение из списка, если это возможно.

Функция max() возвращает максимальное значение из списка, если это возможно.

list = [1, 1.5, -50] Вывод:
print(min(list)) -50
print(max(list)) 1.5


Динамическое создание списков

Помимо статического метода создания списка, при котором элементы указываются непосредственно при создании списка, существует динамический метод append(element). Данный метод добавляет указанный элемент в конец списка.

writers = [] Вывод:
writers.append(“Толстой”) [“Толстой”, “Гоголь”, “Чехов”]
writers.append(“Гоголь”)
writers.append(“Чехов”)
print(writers)

При добавлении функции input(), можно создать список со значениями, вводимыми с клавиатуры.

writers = [] Ввод: Вывод:
name1 = input() Толстой [“Толстой”, “Гоголь”, “Чехов”]
name2 = input() Гоголь
name3 = input() Чехов
writers.append(name1)
writers.append(name2)
writers.append(name3)
print(writers)



Строковый метод split()

Метод split() разбивает строку на элементы, разделённые указанным знаком или последовательностью. Если не указать разделитель, то элементы будут разделяться пробелами.

print(“Python is awesome”.split()) Вывод:
print(“192.168.0.1”.split(“.”)) [“Python”, “is”, “awesome”]
[“192”, “168”, “0”, “1”]


Строковый метод join

Метод join собирает строку из элементов списка, используя в качестве разделителя указанную вначале строку.

print(“.”.join([“192”, “168”, “0”, “1”])) Вывод:
print(“ ”.join([“Python”, “is”, “awesome”])) “192.168.0.1”
“Python is awesome”
Перебор значений

Список – итерируемый объект. Это значит, что его элементы можно использовать в циклах, указывая переменную.

a = [1, 2, 3] Вывод:
for i in a: 1
    print(i) 2
3


Методы списков

1. Метод append(element) добавляет один элемент в список.

2. Метод extend(list) расширяет список другим списком.

3. Метод insert(index, element) вставляет новый элемент в список.

4. Метод index(element) находит индекс переданного элемента.

5. Метод remove(element) удаляет элемент из списка по его значению.

6. Метод reverse() меняет порядок списка на обратный.

7. Метод count(element) подсчитывает количество определенных элементов в списке.

8. Метод sort(reverse= (True или False)) упорядочивает список по возрастанию или убыванию.

9. Метод clear() удаляет все элементы из списка, делая его пустым.

10. Метод pop(index) удаляет элемент по индексу и выводит его в консоль. Если не указать индекс, удалится последний элемент списка.

11. Метод copy() делает копию списка, независимую от исходного. Эту копию можно сохранить в другую переменную и изменять в программе.

12. Оператор del позволяет удалять элементы списка по определенному индексу.


Кортежи

Кортеж – это неизменяемый список, который может содержать значения разных типов. Кортеж допускает неограниченную вложенность. Кортежу присущи все методы списков, за исключением тех, которые изменяют содержимое списка.
Чтобы создать пустой кортеж нужно открыть и закрыть круглые скобки:
empty_tuple = ()

Получить элемент кортежа можно по его индексу:
tuple1 = (1, True, “Python”) Вывод:
print(tuple1[1]) True

Преимуществом кортежей является скорость их обработки, так как они неизменяемы, операции над ними совершаются в разы быстрее, чем над списками. Также, кортежи – это гаранты безопасности данных, так как кортеж – неизменяемый тип данных.


Функция tuple()

Функция tuple() приводит список к кортежу. Например:

list = [1, True, “Python”] Вывод:
tuple1 = tuple(list) (1, True, “Python”)
print(tuple1)


Множества

Множество – это структура данных, похожая на математическое множество. все элементы множества различны (уникальны), два элемента не могут иметь одинаковое значение; множества не упорядочены, то есть элементы не хранятся в каком-то определенном порядке; элементы множества должны относиться к неизменяемым типам данных; хранящиеся в множестве элементы могут иметь разные типы данных.

Чтобы создать множество, нужно перечислить его элементы в фигурных скобках:
set1 = {1, True, “Python”}

Чтобы создать пустое множество используется функция set():
set2 = set()

Если просто открыть и закрыть фигурные скобки ({}), создастся пустой словарь, не множество.


Операции над множествами

1. Объединение множеств;

2. пересечение множеств;

3. разность множеств;

4. симметрическая разность множеств.


Объединение множеств

Объединение множеств – это создание множества из элементов, принадлежащих хотя бы одному из исходных множеств. Для этой операции используется метод union().

set1 = {1,2,3,4} Вывод:
set2 = {1,2,6,7,5} {1, 2, 3, 4, 6, 7, 5}
set3 = set1.union(set2)
print(set3)


Пересечение множеств

Пересечение множеств – это множество из элементов, одновременно принадлежащих каждому из исходных множеств. Для нахождения пересечения множеств используется метод intersection():

set1 = {1,2,3,4} Вывод:
set2 = {1,2,6,7,5} {1, 2}
set3 = set1.intersection(set2)
print(set3)


Разность множеств

Разность множеств – это множество, в которое входят все элементы первого множества, не входящие во второе множество. Для этой операции существует метод difference():

set1 = {1,2,3,4} Вывод:
set2 = {1,2,6,7,5} {3, 4}
set3 = set1. difference(set2)
print(set3)


Словари

Словари – изменяемые коллекции элементов с произвольными индексами – ключами. Если в списках элементы индексируются целыми числами, начиная с 0, то в словарях — любыми ключами, в том числе в виде строк.

Чтобы создать словарь, нужно перечислить его элементы, пары ключ—значение, через запятую в фигурных скобках, как и элементы множества. Первым указывается ключ, после двоеточия — значение, доступное в словаре по этому ключу.

dict1 = {
“name”: “Alexandr”
“surname”: “Pushkin”
“birthday”: (6, “June”, 1799)}

Чтобы создать пустой словарь, достаточно открыть и закрыть фигурные скобки или использовать функцию dict():

empty_dictionary = {}
empty_dictionary2 = dict()

Получить элемент словаря можно по его ключу:

dict1 = { Вывод:
“name”: “Alexandr” “Alexandr”
“surname”: “Pushkin”
“birthday”: (6, “June”, 1799)
}
print(dict1[“name”])


Функция zip()

Функция zip() позволяет создать словарь из двух списков:

keys = [“name”, “surname”, “birthday”]
values = [“Alexandr”, “Pushkin”, (6, “June”, 1799)]
dict1 = dict(zip(keys, values))
print(dict1)
Вывод:
{
“name”: “Alexandr”
“surname”: “Pushkin”
“birthday”: (6, “June”, 1799)
}


Методы словарей

1. Метод items() возвращает словарные пары ключ: значение, как соответствующие им кортежи.

2. Метод keys() возвращает список ключей словаря.

3. Метод values() возвращает список значений словаря.


Функции

Функция – это фрагмент кода, выполняющий какие-то операции, имеющий своё имя, подобно переменной.

Для создания функции используется инструкция def:
def name(parameters):
pass

При именовании функций соблюдаются те же правила, что и при именовании перемен-ных. Функция может принимать параметры, которые указываются при её создании; а мо-жет не принимать параметров, в таком случае, при создании функции ставятся пустые скобки. На месте «pass» пишется блок кода функции, который отделяется отступом, обычно в 4 пробела.


Инструкция pass

Инструкция «pass» пишется там, где ещё не дописан код, и говорит интерпретатору о том, что данное место следует пропустить, не вызывая ошибок. Ошибок не будет, если до инструкции их не было.


Параметры функции

Параметры функции указываются при её создании в круглых скобках. При этом можно указать только имя параметра, тогда в качестве него будет приниматься любой тип данных; а можно указать тип данных параметра по следующему принципу: def name(parameter:type).

Например:

def print3(element):
print(element)
print(element)
print(element)

Данная функция будет выводить указанный элемент 3 раза, независимо от типа параметра.

Другой пример:

def summ(summand1:float, summand2:float):
summ = summand1+summand2
if summ == int(summ):
print(int(summ))
else: print(summ)

В данном случае подразумевается, что оба параметра будут иметь тип float. При наведении на имя функции будет появляться подсказка с описанием функции и указанием типа параметров.

Также, в параметрах допустимо указание их неограниченности, посредством указания *args или **kwargs. В первом случае будет подразумеваться ввод некоторого числа параметров, которые будут обрабатываться, как список. Во втором случае подразумевается ввод некоторого числа именованных параметров, обрабатывающихся, как словарь.

Во втором случае значение параметров нужно присваивать к переменной, имя которой будет использоваться, как ключ словаря.

Например: Вывод:
def ToBuy(*args): “Список покупок”
print(“Список покупок”) “Хлеб”
for i in args: “Батон”
print(i) “Молоко”
ToBuy(“Хлеб”, “Батон”, “Молоко”)

Чтобы вызвать функцию в программе, нужно написать её имя, поставить круглые скобки и перечислить в них параметры, если они требуются.

Пример с использованием **kwargs:

def Pets(owner:str, **kwargs): Вывод:
print(f“Owner: {owner}”) “Owner: Andrew”
for pet, name in kwargs.items(): “dog: Sharik”
print(f”{pet}: {name}”) “cat: Murka”
Pets(“Andrew”, dog = “Sharik”, cat = “Murka”)

*args и **kwargs – это условные обозначения, вместо них, после «звёздочек» могут стоять произвольные названия. Например: *things, **pets.

При упоминании *args или **kwars внутри функции (не в параметрах), «звёздочки» не указываются.

Следует понимать, что переменные, объявленные внутри функции или в параметрах, являются локальными и доступны только данной функции. Глобальная же переменная доступна во всей программе, но при её использовании внутри функции, нужно указать, что она глобальная:

a = 1 Вывод:
def increment(): 3
global a
a = a + 1
increment()
increment()
print(a)


Инструкция return

Инструкция return завершает работу функции и возвращает значение. Эта инструкция может возвращать значение любого типа данных.

Для примера работы инструкции переделаем функцию сложения, написанную ранее:

def summ(summand1:float, summand2:float): Вывод:
summ = summand1+summand2 4
if summ == int(summ):
return int(summ)
else: return summ
print(summ(1, 3))

Чтобы вывести значение, возвращаемое при помощи return, нужно функцию заключить в print(), как сделано в предыдущей программе.


Рекурсия. Работа с функциями: functools и лямбда функции


Рекурсия

Рекурсия – это явление вызова функции внутри этой же функции. То есть, это случай, когда функция вызывает саму себя. Хорошим примером рекурсии является функция, находящая факториал числа:

def factorial(n):
    if n == 1:
        return n
    else:
        return n*factorial(n-1)


Виды рекурсии

Рекурсию можно назвать простой, если в функции присутствует лишь один рекурсивный вызов. Такую рекурсию можно назвать еще рекурсией первого порядка. Но рекурсивный вызов может появляться в функции более, чем один раз.

• Параллельная рекурсия - тело определения функции function_1 содержит вызов некоторой функции function_2, несколько аргументов которой являются рекурсивными вызовами функции function_1.

• Взаимная рекурсия - в теле определения функции function_1 вызывается некоторая функции function_2, которая, в свою очередь, содержит вызов функции func-tion_1.

• Рекурсия более высокого порядка - в теле определения функции аргументом рекурсивного вызова является рекурсивный вызов.


Лямбда-функции

Лямбда функции в Python – это такие функции, которые не имеют названия. Их также называют анонимными. Слово «lambda» является служебным, и не отражает сути конкретной функции.

Основная причина применения лямбда функций — создание функции, которая используется в коде единожды. Использование таких функций позволяет снизить число строк ко-да, которые вам придется написать.
Создание лямбда-функции: lambda <аргумент(ы)>: <выражение>

Например: lambda x: x**2


Модуль functools

Functools — это библиотека, которая содержит дополнительные функции высших порядков. Чтобы работать с ней, нужно импортировать её целиком, также можно импортировать отдельные части библиотеки. Работа с библиотеками будет рассмотрена в последующей части справочника.


Функция reduce()

Функция reduce()  принимает функцию и последовательность. Запускает цепь вычислений, применяя функцию ко всем элементам последовательности. Сводит набор к единственному значению.
from functools import reduce Вывод:
res = reduce(lambda sum, x: sum+x, [0.1, 0.2, 0.7]) 1
print(res)
Данный код вернёт сумму элементов переданного списка. В качестве функции в коде используется лямбда-функция с параметрами sum и x.


Функция partial()

Функция partial() позволяет изменить количество параметров функции, путём присваивания другим параметрам определенного значения.

import functools
# допустим у нас есть какая-то функция
def set_stars(amount, type):
    print(type, amount)
# уменьшаем число аргументов set_stars с partial
print_neutron_star = functools.partial(set_stars, type='Neutron stars: ')
print_neutron_star(1434)
Вывод: Neutron stars:  1434


Функция cmp_to_key()

Возвращает ключевую функцию для компарации объектов.

def num_compare(x, y):
    return y - x
print(sorted([4, 43, 1, 22], key=functools.cmp_to_key(num_compare)))
Вывод: [43, 22, 4, 1]


Функция update_wrapper()

Используется для обновления метаданных функции-обертки, данными из некоторых атрибутов оборачиваемой функции. Обеспечивает лучшую читаемость и возможность повторного использования кода.


@total_ordering

Это декоратор класса, в котором задаются методы сравнения.


@wraps

Декоратор применяется к функции-обертке. wraps обновляет функцию-обертку так, что-бы она выглядела как оборачиваемая функция. При этом копируются атрибуты __name__ и __doc__.


Функции высшего порядка

В программировании (и в математике) функциями высшего порядка называются функции, которые выполняют одно (или оба) из этих действий:

1. Принимают одну (и более) функций в качестве аргументов.
2. Возвращают функцию в качестве результата.

Пример:

def higherorder(function):  # функция высшего порядка
    return function(15)
def multiply(x): # функция первого порядка
    return x * x
def power(x): # функция первого порядка
    return x ** x
def add(x): # функция первого порядка
    return x + x
def subtract(x): # функция первого порядка
    return x - (x * x)
print(higherorder(multiply))
print(higherorder(power))
print(higherorder(add))
print(higherorder(subtract))


Немного о декораторах

Синтаксис Python позволяет использовать декораторы для получения результата «прохождения» функции первого порядка через функцию высшего порядка. Декоратор – это функция высшего порядка, которая принимает функцию первого порядка и добавляет в результат что-нибудь от себя, не вмешиваясь в логику полученной функции.

Подробнее эта тема будет рассмотрена в другой части справочника.


Ещё о функциях

Функции могут быть параметрами других функций:

def greet(name):
return f‘Привет, {name}’
def message(greet)

Также, в Python допускается вложенность функций:

def Func1(): #Определение функции 1
def Func2(): #Определение функции 2 внутри функции 1
<code> #Блок кода
Func2() #Вызов функции 2 внутри функции 1
Func1() #Вызов функции 1 в основной программе

При использовании подобного кода будут выполнены команды “<code>”, так как после определения функции 2 сразу идёт её вызов, а сама функция является дочерней для “Func1”.


Работа с файлами

Файл — именованная область данных на носителе информации. Обычно, после работы с файлом, в нём сохраняется информация, с которой можно работать в дальнейшем.
Процесс сохранения информации называется «запись данных» в файл.

Процесс извлечения данных из файла называется «чтение данных» из файла.

Когда в программе используется файл, как правило требуется выполнить три шага:

1. Открыть файл. В процессе открытия файла создается связь между файлом и программой. Открытие файла вывода обычно создает файл на диске и позволяет программе записать в него данные. Открытие файла ввода позволяет программе прочитать данные из файла.
2. Обработать файл. На этом шаге данные либо записываются в файл (если это файл вывода), либо считываются из файла (если это файл ввода).
3. Закрыть файл. После использования файла программой его нужно закрыть, тем самым освободить ресурс и разорвать связь файла с программой.

Типы файлов

Существует два типа файлов: текстовые и двоичные (бинарные).
 
Текстовый файл содержит данные, которые были закодированы в виде текста при помощи такой схемы кодирования, как ASCII или Unicode. Даже если файл содержит числа, эти числа в файле хранятся как набор символов. В результате файл можно открыть и просмотреть в текстовом редакторе, таком как «Блокнот».

Двоичный файл содержит данные, которые не были преобразованы в текст. Данные, ко-торые помещены в двоичный файл, предназначены только для чтения программой, и такой файл невозможно просмотреть в текстовом редакторе.


Виды путей до файла

Чтобы начать работать с файлом, открыть его, нужно знать путь до файла.
Путь до файла – это строка, в которой определённым способом указаны папки, ведущие к файлу, расположенному на диске.

Путь может быть абсолютным и относительным.

Абсолютный путь – это строка, в которой вся информация указана непосредственно в полном виде. Например: “C:\Users\Documents\file.txt”.

Относительный путь – это строка, в которой часть информации указана специальными символами. Например: “./file.txt”.


Часто используются сокращения, приведённые в таблице 1.

Таблица 1
Сокращение Значение Пример
./ Текущая директория ./file.txt
../ Предыдущая директория ../file.txt
 ~ Домашняя директория ~/file.txt


Открытие файла

Открыть файл можно с помощью функции open(), сохранив его в переменную:

переменная = open(“путь до файла”, “режим доступа”, encoding = “кодировка”)

Переменная – имя переменной, которая ссылается на файловый объект.

Путь до файла – строка, задающая имя файла (или путь до него).

Режим доступа – строка, задающая режим доступа (чтение, запись, и т.д.), в котором файл будет открыт.

Указывать кодировку не обязательно, но следует, если файл отличается имеет определенную кодировку, не являющуюся основной.


Режимы доступа указаны на иллюстрации.
 
Закрытие файла

После работы с файлом, его принято закрывать. Чтобы закрыть файл используют метод close():

file.close()


Чтение содержимого файла

Для чтения содержимого открытого для чтения файла используются три файловых метода:

; read() – читает все содержимое файла;
; readline() – читает одну строку из файла;
; readlines() – читает все содержимое файла и возвращает список строк.

read()

Файловый метод read() считывает все содержимое из файла и возвращает строку, которая может содержать символы перехода на новую строку '\n'. Пример кода:

file = open(“file.txt”, “r”, encoding=“utf-8”)
data = file.read()
file.close()

Содержимое файла сохранится в переменной «data».

readline()

Файловый метод readline() считывает одну строку из файла  (до символа конца строки '\n'). Для удаления символа '\n' из конца считанной строки удобно использовать строковый метод rstrip(). Пример кода:

file = open(“file.txt”, “r”, encoding=“utf-8”)
data = file.readline().rstrip()
file.close()

В переменной «data» сохранится одна строка без переноса.

Метод readlines()

Считывает все строки из файла и возвращает список из всех считанных строк.

Пример кода:

file = open(“file.txt”, “r”, encoding=“utf-8”)
data = [line.rstrip() for line in file.readlines()]
file.close()


Запись данных в файл

; write() – записывает переданную строку в файл;
; writelines() – записывает переданный список строк в файл.

write()

файл.write(“строковое значение”)

Для записи данных в файл он должен быть открыт для записи (режимы 'w', 'а', 'r+'), ина-че произойдет ошибка.

Если файл открыт в режиме 'w', то его содержимое сначала полностью стирается, а уже затем в него добавляются данные.
writelines()

Последовательные вызовы метода write() дописывают текст в конец файла.
На практике часто приходится записывать в файл содержимое целого списка. Это можно сделать с помощью цикла или метода writelines(), что удобнее.
 
Метод writelines() принимает в качестве аргумента список строк и записывает его в файл.

файл.writelines(список строк)

print()

Для записи данных в файл можно также использовать встроенную функцию print(). Для этого нужно передать ей еще один именованный аргумент file, указывающий на открытый файл. При этом функция print() автоматически добавляет переход на новую строку. Пример кода:

file = open(“file.txt”, “w”)
print(“string”, file = file)
file.close()

В файл сохранится строка “string\n”.


Конструкция with

Конструкция with применяется для облегчения работы с файлами. Все операции осуществляются внутри конструкции. А после, не нужно закрывать файл, это сделается автоматически. Пример кода:

with open(“file.txt”, “w”) as file:
print(“File’s data”, file=file)

Заключение
В этой части справочника вы познакомились со структурами данных, изучили функциональное программирование и работу с файлами. Полученные знания являются достаточными для того, чтобы писать большинство программ. Конечно, создать программу с графическим интерфейсом вряд ли получится, но написание консольных приложений вам под силу.

В следующих частях будут рассмотрены библиотеки, декораторы, ООП (объектно-ориентированное программирование


Рецензии