Краткое введение в ООП
Объектно-ориентированное программирование (ООП) – технология разработки сложного программного обеспечения, в которой программа строится в виде совокупности объектов и их взаимосвязей.
Объединение данных и действий, производимых над этими данными, в единое целое, которое называется объектом – является одним из основных принципов ООП.
Основными понятиями являются понятие класса и объекта.
Класс является типом данных, определяемым пользователем и представляет собой структуру в виде данных и методов для работы с данными.
Формально Класс — это шаблон, по которому будет сделан объект.
Объект является экземпляром класса. Объект и экземпляр - это одно и то же.
Вот пример. Форма для изготовления печенья – это класс, а само печенье это объект или экземпляр класса, т.е. это конкретное изделие. Печенье имеет размеры, цвет, состав – это атрибуты класса. Также в классе описываются методы, которые предназначены для чтения или изменения данных объекта.
В Python характеристики объекта, называются атрибутами, а действия, которые мы можем проделывать с объектами, — методами. Методами в Python называют функции, которые определяются внутри класса.
Объект = атрибуты + методы
Список
Список (list) представляет тип данных, который хранит набор или последовательность элементов. Для создания списка в квадратных скобках через запятую перечисляются все его элементы.
Создание пустого списка
numbers = []
Создание списка чисел:
numbers = # имя списка numbers, он содержит 5 элементов
Создание списка слов:
words = # имя списка words, он содержит 4 элемента
Создание списка из элементов разного типа
listNum = # имя списка listNum, список содержит целые числа и строки
Для управления элементами списки имеют целый ряд методов. Некоторые из них:
append(item): добавляет элемент item в конец списка
insert(index, item): добавляет элемент item в список по индексу index
remove(item): удаляет элемент item. Удаляется только первое вхождение элемента. Если элемент не найден, генерирует исключение ValueError
clear(): удаление всех элементов из списка
index(item): возвращает индекс элемента item. Если элемент не найден, генерирует исключение ValueError
pop(): удаляет и возвращает элемент по индексу index. Если индекс не передан, то просто удаляет последний элемент.
count(item): возвращает количество вхождений элемента item в список
sort(): сортирует элементы. По умолчанию сортирует по возрастанию. Но с помощью параметра key мы можем передать функцию сортировки.
reverse(): расставляет все элементы в списке в обратном порядке
Кроме того, Python предоставляет ряд встроенных функций для работы со списками:
len(list): возвращает длину списка
sorted(list, ): возвращает отсортированный список
min(list): возвращает наименьший элемент списка
Правила написания идентификаторов
Есть некоторые правила написания идентификаторов. Но сначала вы должны знать, что Python чувствителен к регистру. Это означает, что имя и имя – это два разных идентификатора в Python. Вот несколько правил написания идентификаторов в Python:
- Идентификаторы могут быть комбинацией прописных и строчных букв, цифр или символа подчеркивания (_). Итак, myVariable, variable_1, variable_for_print – все это действительные идентификаторы Python.
- Идентификатор не может начинаться с цифры. Итак, пока переменная 1 действительна, переменная 1 недействительна.
- Мы не можем использовать специальные символы, такие как!, #, @,%, $ И т. Д. В нашем идентификаторе.
- Идентификатор может быть любой длины.
Хотя это жесткие правила для написания идентификаторов, также существуют некоторые соглашения об именах, которые не являются обязательными, а скорее являются хорошими примерами, которых следует придерживаться:
- Имена классов начинаются с заглавной буквы. Все остальные идентификаторы начинаются со строчной буквы.
- Если идентификатор начинается с одного символа подчеркивания в начале, это означает, что идентификатор является частным.
- Если идентификатор начинается и заканчивается двумя символами подчеркивания, это означает, что идентификатор является определяемым языком специальным именем.
- Хотя c = 10 действительно, запись count = 10 имела бы больше смысла, и было бы легче понять, что он делает, даже если вы посмотрите на свой код спустя долгое время.
- Несколько слов можно разделить знаком подчеркивания, например this_is_a_variable.
Вот пример программы для переменных в Python:
myVariable="hello world" print(myVariable) var1=1 print(var1) var2=2 print(var2)
Если вы запустите программу, результат будет таким, как на изображении ниже.
Основные элементы языка Python
Язык Python имеет много встроенных типов данных. В этом разделе приводится их перечень, для того чтобы сознательно понимать необходимость преобразования одного типа данных на другой в процессе программирования арифметических и других типов выражений.
Любая конструкция языка программирования начинается с алфавита. Из символов алфавита создаются лексемы (token). Лексема — это минимальная единица языка, которая имеет определенное самостоятельное значение и который понимает транслятор. Если транслятор ее не понимает, то выдается сообщение об ошибке в программе. По умолчанию символы кодируются в системе UTF-8.
Различают следующие виды лексем:
- ключевые (зарезервированные) слова (keywords)
- идентификаторы (identifiers)
- литералы (константы)
- операции;
- знаки препинания.
В языке Python используется несколько десятков ключевых (зарезервированных) слов (например, int, list, input, print, float и др.). С их назначением мы будем знакомиться постепенно, по мере возникновения надобности в их применении.
Идентификаторы (имена) используются для обозначения переменных, функций, которые создает программист, и других объектов. Идентификатор переменной может состоять из латинских букв, цифр и знака подчеркивания. Первым символом имени не может быть цифра или знак подчеркивания.
В системе (среде) программирования IDLE правильные имена переменных высвечиваются черным цветом. Если имя переменной отображается другим цветом, его необходимо заменить. Одинаковые имена с буквами на разных регистрах воспринимаются как разные имена. Например, идентификаторы ster и Ster является разными именами.
Имена переменных используются для доступа к данным. Данные в языке Python представлены в форме объектов. То есть объект — это участок памяти с определенным значением и возможными операциями его обработки. Каждый объект имеет свой тип, например int (целое число), str (строка) и др. В языке Python существуют базовые объектные типы (встроенные в язык) и разрабатываемые пользователем средствами самого языка или другими средствами. Отметим, что переменные хранят не сам объект, а ссылку на объект, то есть адрес объекта в памяти компьютера.
Как уже отмечалось, в языке Python применяется динамическая типизация переменных. Это значит, что не нужно объявлять типы переменных, как это делается во многих языках программирования, поскольку их тип определяется автоматически в процессе присваивания им значений. Этот тип определяется значением, расположенным справа от оператора присваивания, который обозначается знаком (=).
В одной строке можно присвоить одинаковые значения нескольким переменным, например:
Еще раз отметим, что после выполнения оператора присваивания в переменной хранится не сам объект, а лишь ссылка на него, то есть адрес участка памяти, в которой хранится объект. Поэтому следует быть достаточно внимательным при записи групповых операций. Рассмотрим такой фрагмент программы.
Из примера видно, что создается два объекта (х и у) типа list, но они имеют один и ту же адрес памяти, то есть реально создается один объект, значение которого выводится дважды. Для подтверждения этого изменим значение нулевого элемента объекта в (нумерация элементов в списке начинается с нуля) и проверим значения объектов.
Из примера видно, что мы изменили только значение y, а фактически объекты имеют одинаковые значения, потому что реально и х, и у имеют одинаковый адрес, то есть являются одним объектом.
Чтобы получить два объекта х и у, необходимо выполнить присваивание отдельно для каждого из них, например:
Для проверки, ссылаются две переменные на один и тот же объект, используется оператор is. Если переменные ссылаются на один объект, то оператор возвращает значение True, иначе — значение False.
Одним оператором присваивания можно присвоить различные значения нескольким переменным. В таком случае переменные и значения отделяются запятой, например:
Количество элементов слева и справа от оператора присваивания должно быть одинаково, иначе будет выдано сообщение о синтаксической ошибке. Например, ошибка будет выдана для такой инструкции:
Избавиться от этого явления можно с помощью символа «звездочка» (*), который размещается перед одной из переменных. В таком случае эта переменная содержит список из всех лишних значений.
Условный оператор if
Оператор if позволяет изменить порядок выполнения операторов в зависимости от истинности или ложности некоторого условия. Формат оператора может быть записан в двух формах: полной и неполной форме.
if условие: # блок if <операторы>else: # блок else <операторы>
Блок инструкций if будет выполнен, если условие истинно. Если условие ложно, будет выполнен блок инструкций else.
В условном операторе может отсутствовать слово else и последующий блок. Такая инструкция называется неполным ветвлением.
Пример 5. Записать следующее выражение на языке Python.Если a > 0, то b = 1, иначе a = 0.
print («Введите значение a: «) a = int(input())if a > : b = 1 else: b = print(«b = «, b)
Условный оператор elif
if условие_1: # блок if <операторы>elif условие_2: # первый блок elif <операторы>elif условие_3: <операторы>...else # блок else <операторы>
Ключевое слово elifрасшифровывается, как else + if. Это конструкция позволяет реализовать алгоритм выбора необходимого варианта из нескольких альтернативных вариантов. Оператор elif позволяет упростить код. Сделать его легче читаемым и позволяет избежать написание несколько условий if.
Когда исполняется инструкция if-elif-else, в первую очередь проверяется условие_1. Если условие истинно, тогда исполняется блок инструкций if . Следующие условия и операторы пропускаются, и управление переходит к оператору за условным оператором if-elif-else.
Если условие_1 оказывается ложным, тогда управление переходит к следующему условию elif, и проверяется условие_2. Если оно истинно, тогда исполняются инструкции внутри первого блока elif. Последующие инструкции внутри этого блока пропускаются. Этот процесс повторяется, пока не находится условие elif, которое оказывается истинным. Если такого нет, тогда исполняется блок операторов else
Пример.
x = int(input()) y = int(input())if x > and y > print("Первая четверть")elif x > and y < print("Четвертая четверть")elif y > print("Вторая четверть")else: print("Третья четверть")
Встроенные функции
print (x, sep = 'y') печатает x объектов, разделенных y
len (x) возвращает длину x (s, L или D)
min (L ) возвращает минимальное значение в L
max (L) возвращает максимальное значение в L
sum (L) возвращает сумму значений в диапазоне L
range(n1,n2,n) (n1, n2, n) возвращает последовательность чисел от n1 до n2 с шагом n
abs (n) возвращает абсолютное значение n
round (n1, n) возвращает число n1, округленное до n цифр
type (x) возвращает тип x (string, float, list, dict…)
str (x) преобразует x в string
list (x) преобразует x в список
int (x) преобразует x в целое число
float (x) преобразует x в число с плавающей запятой
help (s) печатает справку о x
map (function, L) Применяет функцию к значениям в L
Более полный ответ
Используя 64-битный Python 3.6 из дистрибутива Anaconda, с помощью sys.getsizeof, я определил минимальный размер следующих объектов и обратите внимание, что устанавливает и диктует предварительное распределение пространства, поэтому пустые не увеличиваются снова до тех пор, пока установленная сумма (которая может варьироваться в зависимости от языка):
Python 3:
Как вы это интерпретируете? Хорошо, скажем, у вас есть набор из 10 предметов. Если каждый элемент имеет размер 100 байт, то насколько велика вся структура данных? Сам набор равен 736, потому что его размер увеличился до 736 байт. Затем вы добавляете размер элементов, так что всего получается 1736 байт.
Некоторые предостережения для определений функций и классов:
Обратите внимание, что каждое определение класса имеет структуру прокси (48 байт) для атрибутов класса. Каждый слот имеет дескриптор (например, ) в определении класса
Временные интервалы начинаются с 48 байтов на их первом элементе и увеличиваются на 8 каждый дополнительный. Только пустые объекты со слотами имеют 16 байтов, и экземпляр без данных имеет очень мало смысла.
Кроме того, каждое определение функции имеет объекты кода, может быть строки документации и другие возможные атрибуты, даже .
Анализ Python 2.7, подтвержденный с помощью и :
Обратите внимание, что словари ( но не наборы ) получили в Python 3.6
Я думаю, что 8 байтов на каждый элемент для ссылки имеют большой смысл на 64-битной машине. Эти 8 байтов указывают на место в памяти, в котором находится содержащийся элемент. 4 байта имеют фиксированную ширину для юникода в Python 2, если я правильно помню, но в Python 3, str становится юникодом ширины, равной максимальной ширине символов.
(И больше о слотах см. Этот ответ )
Типы из белого списка, рекурсивный посетитель
Чтобы охватить большинство из этих типов самостоятельно, вместо того, чтобы полагаться на модуль, я написал эту рекурсивную функцию, чтобы попытаться оценить размер большинства объектов Python, включая большинство встроенных функций, типов в модуле коллекций и пользовательских типов (со слотами и т. Д.).
Такая функция дает гораздо более точный контроль над типами, которые мы собираемся учитывать при использовании памяти, но при этом существует опасность упустить важные типы:
И я протестировал это довольно случайно (надо было провести модульное тестирование):
Эта реализация разбивается на определения классов и определения функций, потому что мы не обращаемся ко всем их атрибутам, но поскольку они должны существовать в памяти для процесса только один раз, их размер действительно не имеет большого значения.
Более полная функция
Нам нужна функция, которая ищет элементы в списках, кортежах, наборах, диктовках, и , а также в других вещах, о которых мы, возможно, еще не подумали.
Мы хотим положиться на , чтобы выполнить этот поиск, потому что он работает на уровне C (что делает его очень быстрым). Недостатком является то, что get_referents может возвращать избыточные члены, поэтому мы должны убедиться, что мы не удваиваем счет.
Классы, модули и функции являются синглетонами — они существуют один раз в памяти. Нас не очень интересует их размер, так как мы мало что можем с ними поделать — они являются частью программы. Поэтому мы не будем считать их, если на них будут ссылаться.
Мы собираемся использовать черный список типов, поэтому мы не включаем всю программу в наш счетчик размеров.
Чтобы сопоставить это со следующей функцией из белого списка, большинство объектов знают, как обходить себя для целей сборки мусора (это примерно то, что мы ищем, когда хотим узнать, насколько дороги в памяти определенные объекты. Эта функциональность используется .) Однако эта мера будет гораздо более обширной, чем мы предполагали, если мы не будем осторожны.
Например, функции знают достаточно много о модулях, в которых они созданы.
Еще одно отличие состоит в том, что строки, являющиеся ключами в словарях, обычно интернированы, поэтому они не дублируются. Проверка на также позволит нам избежать подсчета дубликатов, что мы и сделаем в следующем разделе. Решение черного списка пропускает подсчет ключей, которые являются строками в целом.
Типы в белых списках, Рекурсивный посетитель (старая реализация)
Чтобы охватить большинство этих типов самостоятельно, вместо того, чтобы полагаться на модуль gc, я написал эту рекурсивную функцию, чтобы попытаться оценить размер большинства объектов Python, включая большинство встроенных функций, типов в модуле коллекций и пользовательских типы (щелевые и другие).
Функция такого типа дает гораздо более детальный контроль над типами, которые мы собираемся рассчитывать на использование памяти, но есть опасность пропустить типы:
И я проверил это довольно случайно (я должен протестировать это):
Эта реализация разбивает определения классов и определения функций, потому что мы не используем все их атрибуты, но поскольку они должны существовать в процессе только один раз в памяти, их размер на самом деле не имеет большого значения.
Строки
Строка – это последовательность символов. Чаще всего строки – это просто некоторые наборы слов. Слова могут быть как на английском языке, так и почти на любом языке мира.
Операции со строками
string извлекает символ в позиции i
string извлекает последний символ
string извлекает символы в диапазоне от i до j
Методы работы сос строками
string.upper() преобразует строку в верхний регистр
String.lower() преобразует в строку в нижний регистр
string.count(x) подсчитывает, сколько раз появляется x
string.find(x) позиция первой строки вхождения x
string.replace(x, y) заменяет x на y
string.strip(x) удаляет как начальные, так и конечные символы x
string.join (List) объединяет список строк
Кавычки
Одинарные кавычки
Строку можно указать, используя одинарные кавычки, как например, ‘Это строка’. Любой одиночный символ в кавычках, например, ‘ю’ — это строка. Пустая строка » — это тоже строка. То есть строкой мы считаем всё, что находится внутри кавычек.
Двойные кавычки
Запись строки в одинарных кавычках это не единственный способ. Можно использовать и двойные кавычки, как например, »Это строка». Для интерпретатора разницы между записями строки в одинарных и двойных кавычках нет.
ВниманиеЕсли строка началась с двойной кавычки — значит и закончиться должна на двойной кавычке. Если внутри строки мы хотим использовать двойные кавычки, то саму строку надо делать в одинарных кавычках.
Театр »Современник»print(‘Театр »Современник»’)
Тройные кавычки
Строка, занимающая несколько строк, должна быть обрамлена тройными кавычками (» » » или »’). Например:
Более полный ответ
Используя 64-битный Python 3.6 из дистрибутива Anaconda, я определил минимальный размер следующих объектов и заметил, что наборы и dicts предварительно выделяют пространство, поэтому пустые не увеличиваются снова до тех пор, пока не будет установлено заданное количество (которое может варьироваться в зависимости от реализация языка):
Python 3:
Как вы это интерпретируете? Допустим, у вас есть набор из 10 предметов. Если каждый элемент имеет размер 100 байт, насколько велика вся структура данных? Набор равен 736 байтам, потому что он увеличился один раз до 736 байт. Затем вы добавляете размер элементов, итого 1736 байт.
Некоторые предостережения в отношении определений функций и классов:
Обратите внимание, что каждое определение класса имеет структуру прокси (48 байтов) для атрибутов класса. Каждый слот имеет дескриптор (например, a ) в определении класса
Слотовые экземпляры начинаются с 48 байтов на их первый элемент и увеличиваются на 8 каждый дополнительный. Только пустые объекты со слотами имеют 16 байтов, а экземпляр без данных не имеет смысла.
Кроме того, каждое определение функции имеет объекты кода, возможно, строки документации и другие возможные атрибуты, даже файл .
Также обратите внимание, что мы используем, потому что мы заботимся об использовании маргинального пространства, которое включает накладные расходы на сборку мусора для объекта,
Также обратите внимание, что изменение размеров списков (например, повторное добавление к ним) заставляет их предварительно выделять пространство, аналогично set и dicts. Из исходного кода listobj.c
Исторические данные
Анализ Python 2.7, подтвержденный и
Обратите внимание, что словари ( но не наборы ) получили в Python 3.6. Я думаю, что 8 байтов на каждый дополнительный элемент для ссылки имеют большой смысл на 64-битной машине
Эти 8 байтов указывают на место в памяти, где находится содержащийся элемент. 4 байта — это фиксированная ширина для юникода в Python 2, если я правильно помню, но в Python 3 str становится юникодом шириной, равной максимальной ширине символов
Я думаю, что 8 байтов на каждый дополнительный элемент для ссылки имеют большой смысл на 64-битной машине. Эти 8 байтов указывают на место в памяти, где находится содержащийся элемент. 4 байта — это фиксированная ширина для юникода в Python 2, если я правильно помню, но в Python 3 str становится юникодом шириной, равной максимальной ширине символов.
И чтобы узнать больше о слотах, см. Этот ответ .
Более полная функция
Нам нужна функция, которая ищет элементы в списках, кортежах, наборах, словарях , и , а также в других вещах, о которых мы, возможно, еще не думали.
Мы хотим положиться на этот поиск, потому что он работает на уровне C (что делает его очень быстрым). Обратной стороной является то, что get_referents может возвращать избыточные члены, поэтому нам нужно убедиться, что мы не дублируем счет.
Классы, модули и функции являются синглетонами — они существуют в памяти один раз. Нас не так интересуют их размеры, потому что мы мало что можем с ними поделать — они являются частью программы. Поэтому мы не будем их подсчитывать, если на них есть ссылки.
Мы собираемся использовать черный список типов, чтобы не включать всю программу в наш счетчик размеров.
Чтобы сопоставить это со следующей функцией из белого списка, большинство объектов знают, как обходить сами себя в целях сборки мусора (это примерно то, что мы ищем, когда хотим узнать, насколько дороги в памяти определенные объекты. Эта функция используется .) Однако эта мера будет гораздо более масштабной, чем мы предполагали, если мы не будем осторожны.
Например, функции довольно много знают о модулях, в которых они созданы.
Другое отличие состоит в том, что строки, которые являются ключами в словарях, обычно интернированы, поэтому они не дублируются. Проверка также позволит нам избежать подсчета дубликатов, что мы и сделаем в следующем разделе. Решение с черным списком полностью пропускает счетные ключи, которые являются строками.
Основные операторы
Оператор
Краткое описание
+
Сложение (сумма x и y)
—
Вычитание (разность x и y)
*
Умножение (произведение x и y)
Деление
Внимание! Если x и y целые, то результат всегда будет целым числом! Для получения вещественного результата хотя бы одно из чисел должно быть вещественным. Пример: 40/5 → 8, а вот 40/5.0 → 8.0
=
Присвоение
+=
y+=x; эквивалентно y = y + x;
-=
y-=x; эквивалентно y = y — x;
*=
y*=x; эквивалентно y = y * x;
/=
y/=x; эквивалентно y = y / x;
%=
y%=x; эквивалентно y = y % x;
==
Равно
!=
не равно
>
Больше
=
больше или равно
Часть после запятой отбрасывается
4 // 3 в результате будет 125 // 6 в результате будет 4
**
Возведение в степень
5 ** 2 в результате будет 25
and
логическое И
or
логическое ИЛИ
not
логическое отрицание НЕ
Атрибуты и методы класса
Атрибуты класса
Характеристики объекта, называются атрибутами и записываются в внутри конструктора с помощью переменной self. Доступ к атрибутам осуществляется через переменную self.
Например, класс имеет атрибут цвет – color, он должен быть записан как
self.color
Методы класса
Методы класса создаются посредством ключевого слова def , имени метода , слова self, которое всегда указывается как первый параметр метода
def имя метода(self, передаваемые параметры): # тело метода
Пример. Создаем метод, который выводит на печать характеристики мяча
def Show(self): print("Мяч: ", self.color, self.size )
Мы определили атрибуты класса и методы. Таким образом, класс для нашего мяча будет выглядеть так:
class Balldef __init__(self, color, size): self.color = color self.size = size def Show(self): print("Мяч: ", self.color, self.size )
Библиотека math
Для проведения вычислений с действительными числами язык Python содержит много дополнительных функций, собранных в библиотеку, которая называется math. Для использования этих функций в начале программы необходимо подключить библиотеку, что делается командой
import math # подключение модуля библиотеки
После подключения программа получает доступ ко всем функциям, методам и классам, содержащимся в нём. После подключения можно вызвать любую функцию из подключенной библиотеки по следующему правилу: указывается имя модуля и через точку имя функции
имя_модуля.имя_функции
Например, пусть мы хотим вызвать функцию вычисления Синус угла, задаваемого в радианахimport math y = sin(5) # ошибка не подключен модуль mathx = math.sin(5) # записываем имя модуля и через точку имя функции
Можно подключать не весь модуль, а какую-то его часть. Например, программист хочет использовать только одну функцию из математической библиотеки math. Если он подключит всю библиотеку, то будет добавлено более 40 функций, которые будут занимать место. Чтобы добавить в проект какую-то часть, используют ключевое слово from
from <имя подключаемого модуля> import <название функции>
Например.
from math import sin # подключена только одна функция siny = sin(5) # операция выполненаx = cos(5) # ошибка функция cos не подключена
Ниже приведен список основных функций модуля math. Некоторые из перечисленных функций (int, round, abs) являются стандартными и не требуют подключения модуля math для использования.