Объектно-ориентированное программирование – это способ введения кодовой информации для создания новой программы. В случае с ООП – это распределение на отдельные объекты и классы. Что представляют собой классы, из чего состоят и как с ними работать – разберем в этой статье.
Что такое объектно-ориентированное программирование в Python
Тот, кто проходил обучение программированию, знает, как писать код в процедурном стиле. Ведь именно с него начинается весь процесс обучения. Что же это такое? По сути, процедурное заполнение представляет собой последовательно заполненный код, состоящий из подпрограмм или функций, растянутый на множество строк.
В то время, когда ООП еще не было изобретено, процедурный код использовался повсеместно. Он уместен для создания программ небольшого размера, и по сей день с успехом используется в некоторых ситуациях. Но в том случае, когда требуется создать более совершенные программы, содержащие коды на 10000 строк и больше, процедурный код доставит массу неудобств. В первую очередь это его создание.
При необходимости внесения корректировок внутри программы, придется проанализировать всю приведенную информацию, на что может уйти не один час, после чего приступить к изменениям.
С появлением ООП решить эту задачу стало намного проще. В основе объектно-ориентированного программирования лежит идея, что все состоит из отдельных объектов взаимодействующих друг с другом посредством программных связей. Каждый объект отвечает за выполнение той или иной задачи, ведя себя обособлено, но являясь частичкой одного большого кода.
Как создавать класс в Python
Класс представляет собой проект объекта. Для примера можно взять небольшой код:
x = "Mike" print(dir(x))
Здесь, в последней строке, можно увидеть переменную «х», которая может выглядеть, как большой объем информации, но в ней имеется множество методов. Для их обнаружения, необходимо вписать ключевое слово dir. Из этого следует, что строка основана на классе, а переменная х является экземпляром класса.
Для создания класса, первоначально потребуется ввести команду class, после чего поставить двоеточие. Далее прописывается описание класса, но этот момент не является обязательным и может быть пропущен по желанию пользователя. Чтобы открыть доступ к строке, введите команду Class._doc_ Для полного ознакомления с классом, рассмотрим из чего он состоит.
Атрибут
Эта часть относится к переменной в классе. Другими словами, все его действия происходят внутри классового кода. Атрибут Class способен создать только одну копию внутри класса. Она же, впоследствии, работает со всеми функциями и объектами этого класса. Если это утверждение разобрать на примере, то оно будет выглядеть следующим образом:
class class_attribute: val = 1 def product(self): class_attribute.val *= 10 print(class_attribute.val) obj1 = class_attribute() obj1.product() obj2 = class_attribute() obj2.product()
Для создания переменной класса используем слово val и придадим ему значение 1. Чтобы получить доступ к переменной val, прописываем ниже функцию product(). Создаем манипуляцию значения, умножив его на 10.
Ниже можно увидеть, что после создания двух объектов копия переменной будет использоваться в них обоих. Так как начальное значение атрибута равно 1, а после оно умножается на 10, то в obj1 мы получим итоговое значение val=10, а вот при вызове obj2, val умножается на 10 и получает значение 100. Как итог на экране высветиться следующее:
10 100
Метод
Это функция, которая является элементом класса, и отвечает за выполнение какого-либо действия. В качестве первого параметра метод принимает экземпляр класса. Чтобы начать им пользоваться, нужно вызвать функцию через объект. Всего различается три вида методов:
- Методы экземпляра класса. Наиболее часто встречающийся метод. В качестве первого аргумента self, экземпляр класса принимает объект класса, указывающий на сам экземпляр. Данный вид метода имеет неограниченное количество параметров. Использование аргумента self поможет поменять состояние объекта и обратиться к другим методам и параметрам, привязанным к нему. К примеру, при использовании атрибута self._class_, возможно получить доступ к атрибутам класса и изменить его состояние. Из этого следует, что экземпляры класса предоставляют возможность изменения состояния отдельного объекта или класса в целом.
- Методы класса. Сущность метода класса в том, что он в качестве параметра cls принимает класс. Декларируя методы, необходимо использовать декоратор classmethod. В отличие от предыдущего метода, метод класса привязан только к классу, но не имеет привязанности к его экземпляру. Метод класса работает над изменением состояния класса, что отражается на всех объектах, содержащихся внутри класса, но он не способен изменить состояние конкретно выбранного объекта.
- Статические методы. Декларация статического метода производится использованием декоратора staticmethod. Характерная особенность этого вида в том, что они не способны изменять состояний класса или их экземпляров. Они работают в статическом состоянии и потому не нуждаются в предварительном записывании первого аргумента.
Конструктор
Объектно-ориентированное программирование характеризует конструктор как метод, проявляемый автоматически при создании объектов. Другими словами, он участвует в построении объектов класса. В каждом языке программирования конструктору дается свое имя, так в Python это метод _init_().
Наличествующие знаки подчеркивания перед и после имени метода, указывают на его принадлежность к группе методов перезагрузки операторов. Присутствие таких методов говорит о возможности участия объектов в операциях сложения, вычитания, вызове как функции и других.
- Отображается символическим значением _init_.
- Его необходимость заключена в создании объекта.
- Через свойства объекта конструктор передает значения аргументов.
- Независимо, какого размера класс, он вмещает только один конструктор.
- В случае невозможности обнаружения конструктором класса, программа переключается на родительский класс.
# Прямоугольник. class Rectangle : 'Это класс Rectangle' # Способ создания объекта (конструктор) def __init__(self, width, height): self.width= width self.height = height def getWidth(self): return self.width def getHeight(self): return self.height # Метод расчета площади. def getArea(self): return self.width * self.height
Создаем объект используя класс Rectangle:
# Создаем 2 объекта: r1 & r2 r1 = Rectangle(10,5) r2 = Rectangle(20,11) print("r1.width = ", r1.width) print("r1.height = ", r1.height) print("r1.getWidth() = ", r1.getWidth()) print("r1.getArea() = ", r1.getArea()) print("-----------------") print("r2.width = ", r2.width) print("r2.height = ", r2.height) print("r2.getWidth() = ", r2.getWidth()) print("r2.getArea() = ", r2.getArea())
Что происходит при создании объекта с помощью класса
Работая над конструированием объекта, программа автоматически запускает конструктор. При этом атрибуты получают значения аргументов.
Конструктор с аргументами по умолчанию
Рассматривая иные языки, можно заметить, что они содержат по несколько конструкторов. Питон допускает использование одного. Но преимущество в том, что возможна установка значений по умолчанию.
Примечание от эксперта! Аргументы, участвующие в построении класса, указываются до аргументов со значениями по умолчанию.
class Person: # Параметры возраста и пола имеют значение по умолчанию. def __init__(self, name, age=1, gender="Male"): self.name = name self.age = age self.gender= gender def showInfo(self): print("Name: ", self.name) print("Age: ", self.age) print("Gender: ", self.gender)
Где gender =”Male” относится к значению по умолчанию. Дальше задаем другие значения:
from person import Person # Создать объект Person. aimee = Person("Aimee", 21, "Female") aimee.showInfo() print(" --------------- ") # возраст по умолчанию, пол. alice = Person( "Alice" ) alice.showInfo() print(" --------------- ") # Пол по умолчанию. tran = Person("Tran", 37) tran.showInfo()
В итоге получаем результат с итоговыми значениями.
Сравниваем объекты
Объекты в Python, создаваемые конструктором, имеют координаты расположения. Что указывает на наличие адреса. Допустим, существует объект АА, ссылающийся на ВВ. В таком случае объекту АА выделяется отдельная ячейка, ведь основным объектом в данном случае считается ВВ.
Оператор ==, прописанный в коде, необходим для проведения анализа: на одну или разные ячейки ссылаются выбранные объекты. Если ссылка ведет к одному месту, то оператор == возвратит True. Для понимания ссылаются или нет выбранные объекты на места с разными адресатами, прописывается другой оператор !=
from rectangle import Rectangle r1 = Rectangle(20, 10) r2 = Rectangle(20 , 10) r3 = r1 # Сравните r1 и r2 test1 = r1 == r2 # --> False # Сравните r1 и r3 test2 = r1 == r3 # --> True print ("r1 == r2 ? ", test1) print ("r1 == r3 ? ", test2) print (" -------------- ") print ("r1 != r2 ? ", r1 != r2) print ("r1 != r3 ? ", r1 != r3)
Где конечным результатом будет:
Что такое атрибуты
В Питоне также существует второе понятие Атрибуты, которое имеет отличие от первого, изученного нами. Если первое относится к «Переменным класса», то второе к «Атрибутам». Разберем на примере:
class Player: # Переменная класса minAge = 18 maxAge = 50 def __init__(self, name, age): self.name = name self.age = age
Атрибут
Для создания объектов из одного класса используются разные ячейки памяти. Следовательно, их атрибуты с одинаковым именем будут ссылаться на различную адресацию. К примеру:
from player import Player player1 = Player("Tom", 20) player2 = Player("Jerry", 20) print("player1.name = ", player1.name) print("player1.age = ", player1.age) print("player2.name = ", player2.name) print("player2.age = ", player2.age) print(" ------------ ") print("Assign new value to player1.age = 21 ") # Присвойте новое значение атрибуту возраста player1. player1.age = 21 print("player1.name = ", player1.name) print("player1.age = ", player1.age) print("player2.name = ", player2.name) print("player2.age = ", player2.age)
Итоговый результат:
В Питоне присутствует возможность создания новых атрибутов для созданных ранее объектов. На примере ниже, можно разглядеть, как для объекта player1 создается атрибут address.
from player import Player player1 = Player("Tom", 20) player2 = Player("Jerry", 20) # Создайте новый атрибут с именем «address» для player1. player1.address = "USA" print("player1.name = ", player1.name) print("player1.age = ", player1.age) print("player1.address = ", player1.address) print(" ------------------- ") print("player2.name = ", player2.name) print("player2.age = ", player2.age) # player2 е имеет атрибута 'address' (Error!!) print("player2.address = ", player2.address)
В результате получаем вывод:
player1.name = Tom player1.age = 20 player1.address = USA ------------------- player2.name = Jerry player2.age = 20 Traceback (most recent call last): File "C:/Users/gvido/class.py", line 27, in <module> print("player2.address = ", player2.address) AttributeError: 'Player' object has no attribute 'address'
Атрибуты функции
Для получения доступа к атрибутам объекта, используется оператор «точка» (к примеру, такие значения: player.age). Для облегчения задачи используют различные функции.
getattr (obj, name[,default]) | Работает над возвратом значений атрибута или проводит установку значений по умолчанию, если они не были обнаружены. |
hasattr (obj, name) | Работает над проверкой атрибута объекта: совершалась ли передача аргументом name. |
setattr (obj, name, value) | Работает над приданием значений атрибуту. При его отсутствии создается новый. |
delattr (obj, name) | Работает над удалением атрибута. |
Разновидности встроенных атрибутов класса
Благодаря тому, что объекты являются дочерними элементами атрибутов встроенного языка Питон, они могут заимствовать некоторые атрибуты от него:
Атрибут | Описание |
_dict_ | Предоставление самых необходимых данных о классе. |
_doc_ | Возвращение строки с описанием класса. При невозможности определения значения, возвращается None. |
_class_ | Возвращение объекта, содержащего информацию о классе. |
_module_ | Возвращение имя модуля класса. При определении класса в выполняемом модуле возвращается _main_. |
Виды переменных класса
Если приходилось сталкиваться с другими языками программирования, такими как Java или C#, то наверняка знаете, что такое Field. Переменные класса в Питоне имеют примерно то же значение.
Совет от эксперта! Для получения доступа к переменной, воспользуйтесь именем, а не его объектом класса. В таком случае не произойдет путаницы между переменной и атрибутами.
Для переменной выделяется отдельная ячейка, и она абсолютна доступна для всех объектов класса.
Варианты составляющих класса или объекта
Чтобы найти все атрибуты, методы, объекты и переменные класса, можно воспользоваться вводом функции dir.
from player import Player # Вывести список атрибутов, методов и переменных объекта 'Player' print(dir(Player)) print("\n\n") player1 = Player("Tom", 20) player1.address ="USA" # Вывести список атрибутов, методов и переменных объекта 'player1' print(dir(player1))
Как результат на экран выведутся следующие значения:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'maxAge', 'minAge'] ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'address', 'age', 'maxAge', 'minAge', 'name']
Заключение
Объектно-ориентированное программирование предусматривает работу с классами, которые были разобраны в данной статье. Что они включают в свой состав. И какие функции, методы и атрибуты используют для выполнения различных действий.