Теперь Кью работает в режиме чтения

Мы сохранили весь контент, но добавить что-то новое уже нельзя

Что такое классы и зачем они нужны?

Я  использую Python для автоматизации некоторых рабочих рутинных задач. Я не программист и изучаю Python просто как хобби.
Но я все не могу понять на интуитивном уровне сути классов. Знаю, что это относится к ООП. Но в чем их суть? В чем преимущества их использования? Почему нельзя просто использовать функции? 
В каких случаях нужно использовать именно классы, а не просто функции?
ПрограммированиеPython+2
Игорь Колесников
  ·   · 14,6 K
Веб-разработчик, геймер, специалист по этике  · 10 нояб 2022
Вам уже дали два отличных книжных ответа, так что давайте я сосредоточусь на вот этом:
Но я все не могу понять на интуитивном уровне сути классов
Давайте сразу определимся: "классы" это сокращение, на самом деле эти сущности называются "классы объектов". Таким образом, "класс" это описание объекта. По одному и тому же определению класса мы можем наштамповать сколько угодно объектов, каждый такой объект будет выглядеть (будет внутренне устроен и будет себя вести) так, как написано в определении его класса.
Но в чем их суть?
Моя личная интуиция на тему объектов такая. Объект - это непрозрачный ("чёрный") ящик с кнопками. Каждая кнопка это один из публичных методов класса. В синтаксисе питона:
# см. https://www.youtube.com/watch?v=Z86V_ICUCD4
class БесполезнаяКоробка:
    def __init__(self):
        self.закрыта = True

    def закрыть(self):
        self.закрыта = True

    def открыть(self):
        self.закрыта = False
        self.закрыть()
Эта конструкция определяет класс объектов под названием `БесполезнаяКоробка` (да, вы можете объявлять идентификаторы кириллицей). У объектов этого класса два метода: "закрыть" и "открыть". В интуиции, которую я описываю, эти методы это "кнопки" на ящике. Мы нажимаем на кнопку ("вызываем метод"), тело метода выполняется.
Когда у нас есть класс объектов, мы можем собственно создавать эти объекты, используя специальный метод под названием "конструктор". В питоне это метод `init`. Традиционно во множестве языков (но не во всех) объекты ("экземпляры класса") создаются ключевым словом `new`, но в питоне объекты создаются "вызовом" (применением оператора вызова функции) самого имени класса:
к = БесполезнаяКоробка()
В результате в переменной `к` у нас появляется объект, то есть, некая сущность, у которой можно вызывать методы и которую, что гораздо, гораздо важнее, мы можем передавать в другие функции точно так же, как числа, строки и любые другие данные. Сам класс как таковой (в исходной идеологии ООП) это эфемерная идея, в процессе работы программы больше не существующая.
В питоне есть эта идиотская конвенция, при которой вы вынуждены методы класса объявлять со специальной переменной self в качестве первого аргумента, и это вас, скорее всего, путает. Значением self является конкретный объект, у которого мы в данный момент вызываем этот метод. В (нормальных) языках с более удобной реализацией ООП текущий объект обычно подразумевается, и традиционно доступен в телах методов автоматически по ключевому слову `this`.
И последний элемент объектов класса это их свойства. То есть, у БесполезныхКоробок есть не только две "кнопки" "закрыть" и "открыть", у них ещё есть внутреннее состояние, описанное свойством "закрыта". Технически питон заставляет вас видеть все внутренние кишки его реализации ООП, поэтому это свойство — это буквально свойство переменной self, которую вы же и ожидаете в качестве аргумента init, но это детали реализации, в C++ вы, например, свойства объектов класса определяете непосредственно в теле самого класса (как это и должно выглядеть). Свойств может быть сколько угодно, и их значениями могут быть в том числе другие объекты (скорее всего, других классов).
В чем преимущества их использования?
Самое очевидное преимущество от использования объектов классов такое же, как от использования данных типа Dict. Вы можете в одну переменную (по одному имени) записать очень много данных, и единым целым передавать их из функции в функцию. Более того, когда вы передали эти данные куда-то глубоко в вашем проекте, неважно, насколько глубоко, методы этих объектов будут доступны непосредственно на самих объектах, вам не нужно их `import`ить. Кроме того, класс объектов добавляет в лексикон вашего проекта новое имя, новую концепцию, которую вы можете (и должны) использовать для того, чтобы более выразительно описать решение ваших задач.
Если вас не интересует возможность полиморфных вызовов функций, вы в современных мейнстримных языках можете полностью повторить всю базовую функциональность объектной системы, используя только функции и переменные. Просто при достижении определённой сложности проекта никто больше не сможет это чудовище сопровождать. 
Лучшее, что вы можете для себя сделать, если вы действительно хотите понять объектно-ориентированный подход к разработке программного обеспечения - это прочитать книгу одного из непосредственных авторов всей этой концепции, Object-Oriented Analysis and Design.
Почему нельзя просто использовать функции?
Если в вашем языке функции могут быть замыканиями (а в любом мейнстримном языке в 2022 году это так), то вы можете полностью сымитировать большую часть ООП только на замыканиях. Я об этом выше уже сказал. Авторы Structure and Interpretation of Computer Programs посвятили этому целую главу, при этом в языке Scheme никакой поддержки "классов" нет.
Так что функции, конечно же, можно "просто" использовать. На жабоскрипте, например, классов как таковых вообще нет - конструкторы это тоже просто ещё одна функция, для которой начинает работать синтаксический сахар в виде this и new. И ничего, пишут на этой насмешке над языками программирования как-то сотни тысяч людей.
Вопрос только в том, сможете ли вы при помощи одних только функций и структур данных описать решение вашей задачи так, что в нём сможет кто-нибудь кроме вас разобраться через несколько лет.
ООП это в первую очередь парадигма проектирования приложения, а не программирования.
В каких случаях нужно использовать именно классы, а не просто функции?
Допустим, я пишу файловый менеджер, и мне нужно спроектировать то, как я буду манипулировать списком файлов, который видит в данный момент пользователь.
Я могу организовать какую-то глобальную переменную `filesList`, которая является массивом структур `File`. Если у меня в языке нет поддержки структур (ну, когда-то давно и такое тоже было), то значит, у меня целый винегрет таких массивов: `fileNamesList`, `fileSizesList`, `fileTypesList`. Но не будем о таких ужасах, структуры данных есть сегодня везде. И мне нужно организовать для каждого возможного действия над файлами по функции: `openFile`, `deleteFile`, `showFileProperties`, и т. д.
Теперь вспомним, что файлы, они разных типов бывают, а значит, нам нужно делать разные вещи в `openFile`, в `showFileProperties` и т. д., во всех них, в зависимости от типа. Тип мы кодируем ещё одним полем в наших структурах `File`, а в функциях у нас гигантские `switch…case`. Всё это нужно как-то организовать, рассовать в физические файлы исходного кода.
Так, конечно, тоже можно работать, и до определённого момента так и работали.
Теперь представим, что у меня есть элементарная функциональность ООП: я могу объявлять "классы" "объектов", и "объекты" это не просто структуры данных, у объектов кроме свойств есть ещё и методы.
Имея такие инструменты, я могу схлопнуть все мои лежащие по разным местам функции для работы с файлами в одно место: в определение класса `File`, в виде методов с понятными короткими названиями `open`, `showProperties`, `delete`, и т. д. Разные типы файлов я естественным образом выражу в виде отдельных классов `ImageFile`, `TextFile`, `ArchiveFile` и т. д. У каждого из этих классов `open` и остальные методы будут делать что-то своё. Отдельное свойство `type` у файлов и гигантские `switch…case` в телах функций больше не нужны. При этом код, который отвечает за одну и ту же функциональность, находится в одном и том же месте, естественным образом. Более того, я могу в некоторых языках конструировать объекты File на лету, включая их функциональность — прямо в процессе работы программы переконфигурировать, как конкретный объект будет себя вести в ответ на вызов метода `open`. Вам будет очень сложно реализовать такое только на функциях.
Так что самая большая польза от ООП - это абстрагирование. Остальное детали реализации. Вы почитайте книгу, почитайте. В короткой статье на Яндекс.Кью всё не объяснить.
1 эксперт согласен
Спасибо большое за такой подробный и развернутый ответ. Особенно мне было полезно узнать Ваше интуитивное... Читать дальше
Openstack DevOps and IBM/Informix Certified DBA...  · 10 нояб 2022
Python — это «объектно-ориентированный язык программирования». Это означает, что почти весь код реализован с использованием специальной конструкции, называемой классами. Программисты используют классы для хранения связанных... Читать далее
1 эксперт согласен
Если не программист, то суть абстракции класса на примере ящика для деталей автомобиля. Ящик (класс) содержит в... Читать дальше
Инженер путей сообщения – строитель  · 10 нояб 2022
Идея, стоящая за введением класса, может быть сформулирована следующим образом: в классе мы объединяем данные с методами по работе с ними в одном пространстве имён. Да, можно было бы обойтись без классов, понаделать структур... Читать далее
1 эксперт согласен