В жизни мы уже классифицируем все объекты. Например, мы знаем, что есть кружка, у неё есть ручка, характеристики — высота, диаметр, объём, цвет, но их объединяет одно — это кружка.
Давайте продолжим с кружками. ООП позволяет определять классы, потому что компьютер не знает, что такое кружка. Давайте скажем ему:
class Cup:
pass
# pass ничего не делает, это заглушка
Теперь у нас есть класс Cup. Давайте создадим несколько кружек:
FirstCup = Cup()
SecondCup = Cup()
ThirdCup = Cup()
В чём проблемы:
— первое — у класса "кружка" нет никаких параметров — ни ширины, не цвета. Это порождает вторую проблему
— все наши кружки получаются одинаковыми.
Давайте придумаем свойство color и зададим их нашим кружкам:
FirstCup = Cup()
SecondCup = Cup()
ThirdCup = Cup()
FirstCup.cоlor = 'yellow'
SecondCup.cоlor = 'red'
ThirsCup.cоlor = 'green'
Теперь наши кружки различаются. Но мы видим ещё проблемы. Во-первых, если мы создадим новую кружку
NewCup = Cup()
и попытаемся получить её цвет, то получим:
>>> print(NewCup.cоlor)
AttributeError: 'Cup' object has no attribute 'color'
Потому что мы не задавали объекту NewCup свойство color. Во-вторых, задавать каждой кружке цвет неудобно.
Здесь нам и помогут методы — то есть, функции внутри класса. В будущем мы сможем определять любые методы, например, .drink(), чтобы пить из кружки, .clear(), чтобы опустошать её. Но сейчас мы рассмотрим так называемые "магические" методы, и один из них — init. Это метод, который вызывается сам при создании объекта. Давайте модифицируем наш класс так, чтобы при создании объекта класса Сup нам выставлялся цвет по умолчанию, например, белый.
class Cup:
def __init__(self):
self.cоlor = 'white'
Обратите внимание на self. Сюда будет передан сам объект, который мы создаём. Теперь, если мы напишем:
DefaultCup = Cup()
print(DefaultCup.cоlor)
>>> 'white'
мы увидим, что объекту и правда присвоен стандартный цвет. То есть, когда мы хотим присвоить какое-то свойство объекту, мы пользуемся self. (Уточню, что он может называться как угодно, объект передается в первый аргумент независимо от имени, но self — соглашение, да и все IDE его подсвечивают). Разумеется, мы всё ещё можем его переопределить:
DefaultCup.cоlor = 'red'
Вся фишка init заключается в том, что туда можно передавать аргументы. Поэтому init называется конструктором. Давайте изменим класс так, чтобы передавать color в качестве аргумента при создании объекта.
class Cup:
def __init__(self, cup_color):
self.color = cup_color
Теперь мы можем сделать так:
MyCup = Cup('purple')
print(MyCup.cоlor)
>>> 'purple'
Помимо магического метода init есть много других. Вы спрашивали про str, поэтому я расскажу про него.
Как вы знаете, если мы напишем
print(2)
то получим
2
А если напишем
print('asdasdasd')
то получим
asdasdasd
Но если мы попробуем сделать
MyCup = Cup('purple')
print(MyCup)
то получим, например
<__main__.Cup object at 0x0000021CA6D50D90>
То есть, нам сообщают, что MyCup — объект класса Cup и находится в памяти на позиции 0x0000021CA6D50D90. Так происходит, потому что программа не знает, что выводить. Метод str позволяет нам переопределить то, что будет выведено при использовании метода str(), а, соответственно, и print(). Изменим Cup:
class Cup:
def __init__(self, cup_color):
self.color = cup_color
def __str__(self):
return "My super beautiful " + self.cоlor + "cup."
Теперь, если мы напишем
MyCup = Cup('purple')
print(MyCup)
то получим
My super beautiful purple cup.
Магических методов много — они позволяют определить, как на объекты класса будут работать функции, например, len(), операторы ==, !=, >, < и другие. Все магические методы можно найти в документации.
Примечание: Яндекс любит распознавать сочетание .co как ссылку и делать страшное внутри кода, поэтому я заменил букву о на русскую. Обязательно не копируйте мой код, а переписывайте правильно, иначе ничего не будет работать.
В языке прогроммирования (ЯП) Python - всё является объектами. Это означает, что каждый объект имеет методы и свойства.
Класс - это интерфейс объекта.