В Python ужасный ООП. Кликбейтный тезис, который имеет право на существование. Есть много языков, где ООП представлен не в самом классическом виде, ну или так принято считать. Прототипные JavaScript и Lua, Golang с прикреплением методов и прочие. Но «не такой как все» всегда ли синоним слова «неправильный»?  С чего мы вообще вязли, что ООП в Python не такой каким должен быть ООП? Что вообще является точкой отсчёта «правильности» ООП? Smalltalk или Simula 67? Вроде бы объектно-ориентированное программирование – это просто парадигма.. или уже догма?

В этом статье мы попробуем понять:

  • что не так с ООП в Python;

  • чем его ООП отличается от языков с эталонной по мнению многих реализацией ООП: Java, C# и С++;

  • почему разработчики языка Python решили сделать всё именно так.

Реализует этот текст автор YouTube-канала PyLounge Макс. Поехали!

Дисклеймер: В этой статье я хочу высказать свои "рассуждения на тему" и подчёркиваю, что не обладаю монополией на истину. Буду рад осудить альтернативное мнение в комментариях.

Для начала необходимо понять. Чем ООП в Python отличается от классической концепции и реализации в других ЯП.

Парадигма ООП появилась ещё 60-70-х годах XX века. ООП или Объектно-ориентированное программирование — это методология программирования, которая основана представлении программы в виде набора взаимодействующих объектов, каждый из которых является экземпляром класса, а классы образуют иерархию наследования.

Ключевыми особенностями ООП является понятия:

  • абстракция; 

  • инкапсуляция; 

  • наследование; 

  • полиморфизм.

Алан Кэй, создателя языка Smalltalk, одним из «отцов-основателей» ООП, говорил, что ООП подход заключается в следующем наборе принципов:

  1. Всё является объектом.

  2. Вычисления осуществляются путём взаимодействия (обмена данными) между объектами, при котором один объект требует, чтобы другой объект выполнил некоторое действие.

  3. Каждый объект имеет независимую память, которая состоит из других объектов.

  4. Каждый объект является представителем класса, который выражает общие свойства объектов (таких, как целые числа или списки).

  5. В классе задаётся поведение (функциональность) объекта. Тем самым все объекты, которые являются экземплярами одного класса, могут выполнять одни и те же действия.

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

 «ООП для меня означает лишь обмен сообщениями, локальное сохранение, и защита, и скрытие состояния, и крайне позднее связывание». (c) Алан Кэй

  • Другими словами, в соответствии с идеями Алана Кэйя, самыми важными ингредиентами ООП являются следующие:

    1. Передача сообщений (то есть взаимодействие).

    2. Инкапсуляция.

    3. Динамическое связывание.

Другими словами, в соответствии с идеями Алана Кэя, самыми важными ингредиентами ООП является:

  1. Передача сообщений (то есть взаимодействие).

  2. Инкапсуляция.

  3. Динамическое связывание.

Интересно, что указывается именно термин связывание, а терминов наследование и полиморфизм нет. Ведь полиморфизм бывает статический (ранее связывание) – это перегрузки и дженерики (шаблоны).  То есть Кэй, человек, который считается изобретателем термина «ООП» не считал важными частями ООП наследование и полиморфизм. Получается пропорции условны, а границы размыты.

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

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

Под инкапсуляцией стали подразумевать возможность классов содержать данные и методы в себе, которые непосредственно связана с этим классом по смыслу.  При этом одни языки соотносят инкапсуляцию с сокрытием этой информации, а другие (Smalltalk, Eiffel, OCaml) различают эти понятия.

Например, в Java можно определить поле как приватное, и тогда оно будет видно только членам этого класса. Также работает и С++, однако там есть концепция друзей (friend), которые могут видеть приватные поля других классов, что сильно критикуется.

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

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

Абстрагирование (абстракция данных) означает выделение значимой информации и исключение из рассмотрения незначимой. В ООП рассматривают абстракцию данных, подразумевая набор наиболее значимых характеристик объекта, доступных остальной программе.

Класс — универсальный, комплексный тип данных, состоящий из тематически единого набора «полей» (переменных более элементарных типов) и «методов» (функций для работы с этими полями), то есть он является моделью информационной сущности с внутренним и внешним интерфейсами для оперирования своим содержимым (значениями полей).

В центре ООП находится понятие объекта. Объект — это сущность, которой можно посылать сообщения и которая может на них реагировать, используя свои данные. Объект — это экземпляр класса. Данные объекта содержатся в объекте, а не просто лежат внутри программы. Инкапсуляция включает в себя сокрытие (но им не является!).

ООП пытается сделать программное обеспечение похожим на «реальный мир», как его может понять обычный человек.

Современная идея ООП — это синтез всех их идей, а также идей Голдберга, Барбары Лисков, Дэвида Парнаса, Бертрана Мейера, Гюля Ага и других. Но никто из них не может утверждать, что же такое «ООП». Термины развиваются, как и задачи, которые изначально эти инструменты должны были решать.

А что же касаемо Python. Python полностью удовлетворяет всем перечисленным выше требования, а значит является «полностью объектно-ориентированным». ООП – просто стиль.

Однако дополнительные фишки ООП, которые стали ассоциироваться с ООП за счёт их реализации в других объектных языках, несколько отличаются тем, как они реализованы в Python.

Отсутствие модификаторов доступа

В Python отсутствует деление на публичные, защищённые, приватные свойства и методы.  Многие вещи в Python основаны на соглашениях. Сокрытие данных реализуется чисто конвенционально. За счёт соглашения использовать подчёркивание у свойств и методов (защищённые члены). Да, можно использовать двойное подчёркивание, так называемый манглинг. Чисто технически это запрещает прямой доступ к данным и равносильно модификатору приват, но это скорее придуманный адептами классического ООП «грязный хак». Таким образом, в Python нет классического разделения на группы доступа, потому что Python доверяет разработчику. В этом плане Python ближе к С++.

«Да, я знаю, что ты можешь выстрелить себе в ногу, но я верю, что ты этого не сделаешь. Ведь не даром ты столько узнал, прежде чем приступить к написанию кода». (с) Python

Мне кажется, инкапсуляция не так полезна в языке с динамической типизацией.  Выскажу непопулярное мнение – это не добавляет никакой безопасности, она просто дает ощущение безопасности. Если вы грамотный программист, то так или иначе сделаете всё как надо.

Но почему разработчики языка не добавили такой привычный «предохранитель»? Ответ кроется в философии Python. Гвидо не любит что-то скрывать. Как он выразился в одном интервью: «мы все здесь взрослые по обоюдному согласию. Python доверяет вам. Он говорит: «Эй, если хочешь чтобы ковыряться в темных местах, я надеюсь, что у тебя есть уважительная причина, и вы не создаете проблем». Этого тезиса мы ещё коснёмся ниже. Пока просто запомните.

Вообще инкапсуляция – это не совсем про сокрытие. Инкапсуляция определяется как «процесс объединения элементов данных и функций в единое целое, называемое классом» или «отделение реализации от описания». Таким образом, номинально в Python всё соблюдается более чем верно.

Отсутствие интерфейсов

В языке Python нет как таковой конструкции как интерфейс (inteface). К слову в С++ их тоже нет. Но что в Python, что в С++, есть механизмы, позволяющие так или иначе использовать интерфейсы.  Абстрактные классы ­– это хоть и немного другое, но функционалу отвечает и допускает некоторое упрощение концепции. На мой взгляд, отсутствие интерфейсов искусственный механизм избежание неоднозначности. Вот у тебя есть абстрактные классы, вот их и используй. С помощью абстрактных классов можно сделать всё тоже что и с интерфейсами, но не надо заморачиваться. Ведь Python идёт по пути простоты и убирает всё лишнее. Создатели языка даже конструкцию switch case выкинули, дабы "место не занимала".

Множественное наследование

Многие современные языки отказываются от множественного наследования, так как оно многое усложняет. Однако Python хоть и идёт по пути упрощения, но старается выкидывать избыточность, а не функциональность, ведь любое упрощение — это потеря гибкости + см. пункт про доверие своему разработчику. Python думаю, что разработчик, который его использует достаточно умён, чтобы не плодить гигантскую иерархию и победить проблему ромба. Не доверился он разве что, при создании GIL. Но спишем это на ошибки молодости. Кстати, С++ также поддерживает множественное наследование. Так что с этим пунктом всё тоже в рамках закона.

Утиная типизация

Она, конечно, к теме относится косвенно. Но тем не менее, рядом с Python всегда всплывает понятие утиной типизации.  

Если что-то выглядит как утка, плавает как утка и крякает как утка, это наверняка и есть утка.

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

Тут во всей красе демонстрируется один из главных принципов Дзена Python«явное лучше, чем неявное». Если что-то выглядит как утка и крякает, то это утка, к чему погружаться в экзистенциальные копания и вопросы самоопределения? Будь проще и посмотри пример.

Поскольку Duck и Human это разные классы, Python повторно вызывает функцию fly_quack() для экземпляра класса Human. И хотя класс Human имеет похожие методы quack и fly , типы объектов были разными и поэтому все работает правильно и вызываются верные методы.

Константные методы

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

Вообще докопаться ещё можно много до чего. Например, не совсем стандартное описании статических методов и свойств, ключевое слово self, MRO и многое многое другое.

Но Python отвечает всем требованиям парадигмы ООП. Просто многие моменты выполнены не так как у всех. Но на то есть причины.  Гвидо ван Россум при разработке дизайна языка мотивировался выработанным им Дзеном Python, где простое лучше, чем сложное, явно лучше не явного и т.д. Через эту философию красной нитью проходит структура всего языка Python.

The Zen of Python
The Zen of Python

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

По мнению многих Smalltalk — самый чистый ООП язык, но что даёт и какова цена этой чистоты? Можно написать очень хороший объектно-ориентированный код как на Smalltalk, так и на Python.

Python прагматичен. Вводятся концепции, представляющие ценность для разработчика, без особого внимания к теологическим концепциям, таким как «правильный объектно-ориентированный дизайн» и прочее. Это язык для людей, которые хотят сделать свою работу быстро и просто, а как там оно «концептуально» верно, отходит на второй план.

Есть языки, которые идут по одному из двух векторов развития: доверяют разработчику, дают средства и возможности, за что он может заплатить неправильностью своих решений. И языки, которые по максимуму всё запрещают, чтобы писать было просто и топорно. Все решения давно приняты за тебя, всем известно как делать правильно, например, Golang. С такой точки зрения «Почти все «фичи» — это сахарная кола, а программирование — это толстяк с диабетом»».

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

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

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

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

ООП в Python не лучше и не хуже, чем в других языка. Он другой. Такой каким концептуально его видел главный разработчик языка Гвидо ван Россум. ООП в Python это часть Дзена Python. Философии, для которой язык и был разработан.

Проблема в том, что люди пытаются перенять подходы из других языков, а не учатся использовать уникальные сильные стороны Python. У Python довольно надежная объектная модель, но это объектная модель Python, а не C++, Java или…кого-то другого.

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

А Python просто сейчас очень популярен. Он своего рода фронтмен, а тот кто на передовой, того обычно и критикуют. И да, я понимаю, что Python стремится быть как можно более простым, как завещал Эйнштейн: «все должно быть настолько простым, насколько это возможно, но не проще». Однако иногда Python всё же попадает в это «проще» чем надо, что может выливаться в проблемы.

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

Дизайн языка потихоньку меняется. Аннотации типов, разного рода оптимизации говорят о том, что язык и сообщество взрослеют и зреют. Python со времён 2 версии уже сильно изменился и будет продолжать меняться. Как молодой бунтарь контркультуртурщик под призмой времени превращается в консерватора и прагматика, также и Python превратится просто в стабильный качественный инструмент. А на смену ему придёт новая рок-звезда, которая будет вертеть устои инженерной культуры и привлекать школьников.

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

Если мы напишем язык, который смогут использовать идиоты, в конце концов, только идиоты и будут его использовать. И да, это цена, которую придётся заплатить.


Закончу мысль довольно известной фразой: «Есть всего два типа языков программирования: те, на которые люди всё время ругаются, и те, которые никто не использует».

Комментарии (72)


  1. vadimr
    12.11.2022 20:57
    +12

    Большинство предъявленных претензий – это и есть настоящее ООП, как в Smalltalk.


  1. KayAltos
    12.11.2022 21:08
    +10

    "Выскажу непопулярное мнение – это не добавляет никакой безопасности, она просто дает ощущение безопасности. Если вы грамотный программист, то так или иначе сделаете всё как надо...

    Вообще инкапсуляция – это не совсем про сокрытие. Инкапсуляция определяется как «процесс объединения элементов данных и функций в единое целое, называемое классом» или «отделение реализации от описания». Таким образом, номинально в Python всё соблюдается более чем верно."

    Я всегда считал, что инкапсуляция еще и про то, чтобы не допустить некорректное взаимодействие с классом, поэтому насчет безопасности категорически не согласен. При грамотной инкапсуляции классы приобретают интерфейсы взаимодействия, с которыми легко и просто работать при больших объемах кода.
    Речь же не про номинально, а про то, что это дает. А позиция "если вы грамотный специалист - ляпайте везде публичные поля, все равно сделаете как надо"... ну, спорно. Так можно пойти дальше и от функций отказаться - ну, идет у вас везде дубляж, и тут поменять нужно что-то. Сделайте ctrl+F и ищите повторяющиеся куски, вы же грамотный, сделаете как надо.


  1. Chvanikoff
    12.11.2022 21:17
    +2

    Erlang might be the only object oriented language because the 3 tenets of object oriented programming are that it's based on message passing, that you have isolation between objects and have polymorphism.
    (Joe Armstrong, creator of Erlang)

    cmd+f [erlang] - 0 results...



  1. mentin
    12.11.2022 21:17
    +22

    Я со многим соглашусь, но оправдывать что-то в Питоне стремлением избежать избыточности это перебор

    Python идёт по пути простоты и убирает всё лишнее. Создатели языка даже конструкцию switch case выкинули, дабы "место не занимала".

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


    1. KayAltos
      12.11.2022 21:18
      +5

      Конструкцию switch-case в 3.10, кстати, по факту, добавили


      1. evocatus
        13.11.2022 02:30
        +5

        В Python добавили pattern matching, а не "конструкцию switch-case".


  1. aamonster
    12.11.2022 21:56
    +17

    Буду рад осудить альтернативное мнение в комментариях.

    Мелкая опечатка в переводе, доставляющая массу удовольствия)

    А статья в целом, конечно – просто наброс. Концовка позволяет понять, что автор вполне адекватен, не религиозный фанатик. Но информации в ней ноль.


  1. GothicJS
    12.11.2022 23:27
    -6

    А чем пайтон лучше, например, пхп ?


    1. mdevaev
      13.11.2022 01:24
      +6

      1. ddv88
        13.11.2022 07:04

        Почему не с версией PHP4 сравнение?

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

        https://www.techempower.com/benchmarks/#section=data-r21


        1. mdevaev
          13.11.2022 07:29
          +5

          Почему не с версией PHP4 сравнение?

          Потому что фрактал плохого дизайна и общая корявость PHP никуда не делась.

          в бенчмарках производительности пайтон где то аж на 240 месте

          Производительности чего? Давайте конкретизировать, бенчмарк в студию.

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

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


      1. Kpeamop
        14.11.2022 00:12
        +2

        статья 12 года) 10 лет прошло, вы в своем уме?) предлагаю сравнить тогда с питоном 2.5


        1. mdevaev
          14.11.2022 00:36
          -3

          Во-первых, отучаемся хамить незнакомым людям.

          Во-вторых, если хочется поострить - наберитесь минимальной компетентности для этого. Или хотя бы проверяйте свои утверждения. В 2012 году питон 2.5 был давно неактуален, и в ходу был 2.7, а стандартным для долгоиграющих проектов считался 2.6. Ах, да, и еще был 3.2, который уже был лучше чем 2.7.

          В-третьих, конкретику в студию. Может, в PHP что-то капитально изменилось? Исчезли странные языковые конструкции и костыли? Или может повысился средний скилл разработчика PHP? Есть что возразить по поводу указанной статьи? Нет? Я так и думал.


          1. Kpeamop
            14.11.2022 00:43

            во 1х невежды недостойны уважения;

            во 2х раз вы вышли попробовать выйти из невежд, проведите пожалуйста сравнение;

            в 3х - у вас что-то вышло слишком много вопросов для п.3:

            • я? вы и предоставьте конретику, ведь вы же утверждаете, а не я;

            • даже в 5.5 многое уже поменялось, не говоря про 7й или даже 8й;

            • про скилы - нет слов) тут и обсуждать нечего - если бы вы понимали о чем пишете, то и не задавали бы этот вопрос;

            • возражение было в прошлом комментарии;

            • "Нет? Я так и думал." - вы сами с собой общаетесь, может к доктору?


            1. mdevaev
              14.11.2022 00:45

              Еще раз: по существу статьи будут возражения или нет? Вы тут уже достаточно наклоунадили по поводу 2.5, так что теперь я очень внимательно жду от вас оправданий.


              1. Kpeamop
                14.11.2022 00:57

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

                "Вы тут уже достаточно наклоунадили по поводу 2.5" - вы действительно не понимаете к чему был отсыл? случайно не достойный ответ про уровню вменяемости на ваш комментарий? почему вас ваше сообщение устроило, а мое нет, корреляции не улавливаете? так вот попробуйте подумать - это полезно.


                1. mdevaev
                  14.11.2022 01:01

                  четко пояснено 

                  вы в своем уме?) предлагаю сравнить тогда с питоном 2.5

                  Я так понимаю, что "2.5" и "вы в своем уме" - это ваши лучше аргументы. Слив засчитан.


                  1. Kpeamop
                    14.11.2022 01:19

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


                    1. mdevaev
                      14.11.2022 01:20
                      +1

                      Увольте меня от своей клоунады, любезный.


                      1. Kpeamop
                        14.11.2022 01:21
                        -1

                        Идите учите уроки лучше, больше пользы будет.


                      1. mdevaev
                        14.11.2022 01:22

                        Не сублимируйте.


                      1. Kpeamop
                        14.11.2022 01:23

                        Незачем.


                      1. mdevaev
                        14.11.2022 01:25
                        +1

                        Это же вы тут чучелко выдумываете, отправляя меня в школу. Очевидно, вопрос несделанных уроков вас очень беспокоит.


          1. Tony-Sol
            14.11.2022 17:37

            Может, в PHP что-то капитально изменилось?

            вы не поверите - https://habr.com/ru/company/otus/blog/524270/ , https://habr.com/ru/company/otus/blog/524990/


            1. mdevaev
              14.11.2022 17:39

              Позовите, когда завезут строгую типизацию.


              1. Tony-Sol
                14.11.2022 22:20

                Почему все всегда сводится к строгой типизации в пыхе? В питоне как будто бы с ней не меньше проблем


                1. mdevaev
                  14.11.2022 22:25

                  Во-первых, потому что нестрогая типизация - источник проблем.

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

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


                  1. Tony-Sol
                    15.11.2022 00:30
                    +2

                    Во-первых, потому что нестрогая типизация - источник проблем.

                    Не отрицаю, мой поинт был скорее про то, что большая часть упреков в сторону php обычно сводится к этому, но тут как в принципе со всеми языками - "нормально пиши - нормально будет"(с), ведь точно так же можно в typeScript или golang везде писать any, но ведь никто в здравом уме специально себе ноги не отстреливает.

                    Во-вторых, ваш код на питоне некорректен. Почему вы указали модуль в аннотации?

                    Не пишу на питоне в прод, поэтому воспользовался документацией и гуглом, чтобы узнать "а как это вообще в питоне делается". Однако с заменой string на str код по прежнему исполняется как на скриншоте.

                    MyPy это не пропустит.

                    Да, MyPy такой код не пропускает, тем не менее - во время исполнения это работает без ошибок или варнингов, в отличии от php.

                    Кстати, есть ли какой-нибудь линтер для PHP, который отловил бы подобную ошибку не во время исполнения?

                    phpcs + (phpstan | psalm) уже де-факто стандарт для php проектов.

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

                    Давайте, как результат - и там и там фатал, что в принципе равнозначно

                    Так же хочется добавить по треду выше

                    Исчезли странные языковые конструкции и костыли?

                    Нет, не исчезли окончательно, но постепенно уходят. Язык становится чище и это радует. В python в свою очередь также есть очень странные вещи, помимо тех что изначально в статье упоминаются.

                    Или может повысился средний скилл разработчика PHP?

                    Ну это звучит тупо как оскорбление. Мнение о php сложилось из-за массы плохого кода, написанного начинающими разрабами. Сколько такого плохого кода будет на python спустя пару лет, учитывая тонну курсов "стань middle python разработчиком за 1/2/3 час/день/неделя (нужное подчеркнуть)" - можно только воображать.


                    1. mdevaev
                      15.11.2022 00:58

                      нормально пиши - нормально будет

                      Только зачем пользоваться корявыми инструментами, если можно взять нормальные?) PHP - это легаси, больше он ни за чем не нужен.

                      Однако с заменой string на str код по прежнему исполняется как на скриншоте.

                      Потому что это аннотация, а не указание типа переменной.

                      phpcs + (phpstan | psalm) уже де-факто стандарт для php проектов

                      Ну слава богу, хоть это осилили.

                      Давайте, как результат - и там и там фатал, что в принципе равнозначно

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


                      1. Tony-Sol
                        15.11.2022 01:23

                        Потому что это аннотация, а не указание типа переменной.

                        Тогда нужен пример, как правильно писать типы в python

                        Так и что, это действительно включаемая честная строгая типизация?

                        С ограничениями (например нельзя средствами языка указать, что "верну массив и 100% это будет массив интов"), но да - php позволяет писать как строго типизированный код, который, если очистить от $ перед переменными, будет почти не отличим от java, так и вырвиглазные one-file'ы вида "index.php на 17К строк, охапка дров и сайт готов". На мое счастье, второе я видел только в постах и комментах с "критикой" php и ресурсах типа govnokod.ru


                      1. mdevaev
                        15.11.2022 01:28

                        Тогда нужен пример, как правильно писать типы в python

                        Так и писать: "var: str". Но это АННОТАЦИЯ. Она не проверяется при исполнении, это просто метаданные. Технически проверку можно сделать рядом, но это никому не нужно, потому что есть mypy.

                        нельзя средствами языка указать, что "верну массив и 100% это будет массив интов"

                        Ну ептыть. И какая тогда область применения у этой поделки, студенческие курсачи с калькуляторами? В любом большом проекте будут развесистые типы, а для их проверки средств нет.

                        Вот блин, как обычно в PHP. Вроде сделали, а по факту полумера. Именно об этом была та статья про фрактал плохого дизайна: что ни возьми - всё недоделано или сделано через одно место.


                      1. Tony-Sol
                        15.11.2022 02:01

                        Так и писать: "var: str". Но это АННОТАЦИЯ. Она не проверяется при исполнении, это просто метаданные.

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

                        Но это АННОТАЦИЯ. <...> Ну ептыть. И какая тогда область применения у этой поделки, студенческие курсачи с калькуляторами?

                        https://www.phpdoc.org/ - тоже аннотация, на которой могу написать что "вот этот аргумент, это мапа из трех значений, 1 это int|float, 2е - объект, который умеет приводить себя к строке, а 3е - это список мап, каждая из которых имеет ключи 'foo', 'bar' и 'foobar'". Умеют ли аннотации python'а такое - не знаю, не проверял.

                        В любом большом проекте будут развесистые типы, а для их проверки средств нет.

                        Без комментариев

                        То есть без сторонних утилит, вообще ни о какой типобезопасности речи не идет.

                        Какая-то оголтелая уверенность в своей правоте основанная ни на чем и голословные заявления, учитывая околонулевые знания хоть чего-нибудь о php.

                        Я сразу уточнил, но продуктовый код на python'е и не знаю о его трендах и современных практиках, однако при этом я не засираю язык на основании статей 10ти летней давности.

                        За сим не вижу смысла продолжать.


                      1. mdevaev
                        15.11.2022 02:20

                        без костылей типа pydantic типизацию в принципе не сделать получается

                        Вы разницу между аннотациями и указанием типов точно понимаете? По-моему нет.

                        Умеют ли аннотации python'а такое - не знаю

                        В питоне аннотируется практически всё в любых сочетаниях и с любой вложенностью.

                        То есть без сторонних утилит, вообще ни о какой типобезопасности речи не идет.

                        Это просто другой подход. Аннотируете все типы в проекте и при сборке запускаете линтеры. И это все конечно здорово, но вы сами сказали, что даже внутри массива уже проверки не работают. Это детский сад.

                        Какая-то оголтелая уверенность в своей правоте основанная ни на чем

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


                      1. bonArt0
                        15.11.2022 07:18
                        +2

                        Частенько подобные рассказы про "20 лет опыта" и "насмотрелись" идут из частных производственно-цеховых лавочек, где 1-2 балбеса годами врастают в офисные кресла, набирая говнокод за 30К/мес. Иногда это делают даже на каком-нибудь фреймворке 5-летней давности.

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

                        Поэтому оставьте свои 15 лет опыта там, где им место - в первой половине прошлого десятилетия, откуда они и есть. И не загаживайте своим нерелевантным опытом то, в чём не разбираетесь.

                        Успехов!


                      1. mdevaev
                        15.11.2022 12:02

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

                        Мой гитхаб идет первой строчкой в гугле. Можете глянуть, чтобы понять, что ваш комментарий ничего общего со мной не имеет.

                        Успехов!


                      1. bonArt0
                        15.11.2022 14:00

                        При чём тут личность? Я аппелирую к нерелевантному опыту.

                        Вы можете иметь сколь угодно большой стаж, вы даже можете иметь огромный опыт в разработке (что, на секундочку, не равно стажу). Вы можете иметь акк на гитхабе, даже со сколь-нибудь просматриваемыми репозиториями.

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


                      1. mdevaev
                        15.11.2022 14:23

                        Смехотворна здесь только ваша нелепая стадия торга, куда вы съехали, как только ваше чучелко рассыпалось в прах.

                        Далее мы с вами будем говорить только по существу. Ваш коллега выше сказал, что в PHP нельзя указать тип вложенных структур данных, чтобы он проверялся strict types. Это очередная полумера из мира PHP: strict types вроде существует, но по факту во многих случаях бесполезна. Или может мы оба ошибамся и на самом деле strict types в состоянии проверить что-то типа "массива словарей с ключами из строк и значениями из массива интов" (в питоне list[dict[str, list[int]])?

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


                      1. Tony-Sol
                        15.11.2022 14:37

                        в PHP нельзя указать тип вложенных структур данных, чтобы он проверялся strict types

                        Пример такого на python в тред.

                        Без сторонних либ или утилит типа pydantic, mypy, etc.


                      1. mdevaev
                        15.11.2022 14:52

                        А никто и не говорил, что в питоне это есть. Речь идет вот о чем: в питоне строгая динамическая типизация и тайп-хинты, которые проверяются внешними утилитами. В PHP - недострикттайпсы, которые на самом деле проверяют в рантайме лишь ограниченный набор типов, а для всего остального нужно использовать более сложные внешние линтеры.

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

                        По итогу в PHP есть два (может и больше) способа указать типы: в комментариях (не проверяются в рантайме) и в коде (крайне ограниченные в реальном применении). Два корявых инструмента.

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


                      1. Tony-Sol
                        15.11.2022 15:17

                        А никто и не говорил, что в питоне это есть.

                        Весь тред строился на том, что "php плохой в нем нет типизации". И вот оказывается в python ее еще меньше и какой ответ на это "а нам и не надо, у нас внешние утилиты есть" - так и у нас есть, помимо того что язык предоставляет. В пересечения и сложения типов python умеет?

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

                        Заменить в предложении php на python и предложение не перестало быть правдивым.

                        указанием типов в комментариях, замусоривая при этом код

                        код который не код, а аннотация, но при этом выглядит как код, располагается в сигнатуре как код - очень удобно, да

                        Аннотации же в питоне изначально прикручивались как часть синтаксиса

                        И поэтому появились только в 3.5, ага

                        В питоне аннотации пишутся прямо в коде и доступны в интроспекции

                        Ну как бы, аннотации php доступны в рефлексии. И так же используются для сериализации/десериализации объектов уже давно.

                        По итогу как - в php есть строгая типизация для примитивов и классов, в python - этого нет вообще. Но php все равно плохой потому что "нет строгой типизации". Мда

                        авторы питона включили голову

                        и сделали 3ю версию. Если мы оперируем к фракталу плохого дизайна 12го года, легитимно в такое же древнее ткнуть python


                      1. mdevaev
                        15.11.2022 15:29

                        оказывается в python ее еще меньше

                        Почитайте вот, чтобы чушь не нести.

                        Заменить в предложении php на python и предложение не перестало быть правдивым.

                        Нет. Потому что питон нигде не заявляет о том, что типы проверяются. Я у вас не случайно спрашивал, точно ли вы понимаете разницу между типизацией и аннотациями типов. Как видно, не понимаете.

                        код который не код

                        Это код.

                        И поэтому появились только в 3.5, ага

                        Появились тогда, когда в них осознали необходимость. Сели, продумали и сделали.

                        аннотации php доступны в рефлексии

                        Так аннотации или все-таки указанные типы? Я могу сделать аннотацию для упомянутого выше списка словарей и получить ее в рефлексии в PHP?

                        По итогу как - в php есть строгая типизация для примитивов и классов

                        В питоне строгая типизация есть для всего. Еще раз отсылаю вас почитать статью из первого пункта, чтобы понимать, что такое типизация и с чем ее едят.

                        сделали 3ю версию

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

                        к фракталу плохого дизайна

                        Я наглядно показал вам разницу в подходе к проектированию языка у пхп и питона. Ключевой момент - полумеры. Но вы, видимо, просто не понимаете, что такое проектирование.


                      1. Tony-Sol
                        15.11.2022 15:39

                        Почитайте вот, чтобы чушь не нести.

                        Ага, снова 12й - про php прям актуалочка, там же в комментах это и подсветили кстати.

                        Это код.

                        Который не исполняется, что делает его не кодом по определению.

                        Я могу сделать аннотацию для упомянутого выше списка словарей и получить ее в рефлексии в PHP?

                        Да.

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

                        Я про python ничего плохо не говорил и много раз расшаркивался, что на нем не пишу и могу только примерно догадываться как сейчас правильно - вы же такого в отношении php не можете себе позволить. Почему - не мое дело да и все равно уже.


                      1. mdevaev
                        15.11.2022 15:49

                        снова 12й

                        В разновидностях систем типов что-то значительно поменялось с тех пор?

                        подсветили

                        Когда будет полностью строгая типизация, тогда и светите.

                        Который не исполняется, что делает его не кодом по определению.

                        Но ведь исполняется. В какой раз подряд спрошу: вы ТОЧНО понимаете, что такое аннотации? :)

                        Да.

                        Примерчик, пожалуйста.

                        хотите жить в манямире, где php такой плохой и "вот-вот умрет"

                        Я наглядно показал, почему пхп плохой, но аргумент про проектирование вы просто не поняли, а потому пропустили мимо ушей. А что он вот-вот умрет - я не утверждал вообще нигде, так что не надо врать, особенно с кавычками. Мое утверждение - пхп обречен на долгую счастливую жизнь в виде легаси, а начинать на нем новые проекты смысла нет, так как есть инструменты получше.

                        вы же такого в отношении php не можете себе позволить

                        Могу, потому что я не программист-на-языке, как вы, и потому что у меня есть опыт с пхп.


      1. GothicJS
        14.11.2022 20:23

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

        Например, складывается впечатление, что ларавель куда популярнее джанго. Почему ?


        1. mdevaev
          14.11.2022 20:25

          Потому что у PHP низкий порог вхождения, что позволяет нанять множество кодомакак, которые кое-как слепят вам на ларавеле всё что вы хотите (а потом будете страдать при поддержке).


          1. GothicJS
            14.11.2022 21:30
            +1

            Вхождения во что? В ЯП или в веб разработку?

            И так говорят про другие языки:
            js - низкий порог, go - низкий порог, python - низкий порог...


            1. mdevaev
              14.11.2022 21:31

              В разработку на ЯП вообще.


              1. GothicJS
                14.11.2022 21:54

                Ну обычно входят не вообще, а в конкретную область. Для веб разработки на бэке человек должен освоить ряд общих технологий, помимо синтаксиса языка. Синтаксис ЯПа будет самым легким из всего этого.

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


                1. mdevaev
                  14.11.2022 22:22

                  Это всё конечно здорово, но PHP из-за своего корявого дизайна и убогой типизации способствует 1) производству быдлокода 2) большему количеству ошибок, чем другие языки. Это просто факт, подтвержденный десятилетиями существования PHP, и спорить с ним глупо. Веб-макаку легко обучить делать на нам лендинги и легко набрать гору макак в ближайшем магазиностроительном вузе, которые сделают вам онлайн-магазин, но когда это станет большим и сложным проектом, его поддержка усилиями дорогих специалистов превратится в ад.


    1. BakinSergey
      13.11.2022 07:52
      -1

      всем


    1. Kpeamop
      13.11.2022 07:52
      +2

      удачным пиаром во время кризиса пхп 5.2-5.3, все сравнение этих двух языков обычно строится на проблемах в пхп этих версий


    1. GothicJS
      13.11.2022 23:56

      Мне вот очень интересно, что в голове у людей, которые заминусовали вопрос "чем пайтон лучше пхп"......вопрос, карл)


      1. Kpeamop
        14.11.2022 00:09
        -1

        это школоло понабежало и дало свое экспертное мнение) ровно так же и оценка питона ими производится)


  1. fuwiak
    13.11.2022 02:44
    +4

    Все об ООП в Python хорошо, просто автор немного недостаточно образован и не совсем понимает, о чем он пишет...


  1. Pfinash
    13.11.2022 07:52

    Создатели языка даже конструкцию switch case выкинули, дабы "место не занимала"

    Добавили в 3.10


    1. dopusteam
      13.11.2022 08:27

      Где?


      1. Pfinash
        13.11.2022 09:14
        -1

        1. dopusteam
          13.11.2022 09:23
          +2

          Это немного другое, что упоминается в статье по второй ссылке, кстати

          Очень важно не путать pattern matching и switch/case,


    1. PyLounge Автор
      13.11.2022 09:14
      +1

      Они добавили Pattern matching. Это далеко не одно и то же


      1. Pfinash
        13.11.2022 10:01
        +3

        И в чем принципиальное отличие, что можно сделать с switch-case чего нельзя match-case?


        1. Hivemaster
          13.11.2022 10:45
          -2

          Что можно сделать - это неправильный образ мысли. Можно и микроскопом гвозди забивать.


        1. danilovmy
          13.11.2022 12:16

          Ну если очень надо найти кто что может - проверка класса объекта в матч кейс питона очень геморно сделано. Мне свитч бы больше зашёл, но нет его в питоне. Свитч это if-else-if-... А паттерн матчинг - это паттерн матчинг.

          Вот это имею ввиду - https://peps.python.org/pep-0634/#class-patterns


          1. Pfinash
            13.11.2022 21:34
            +1

            Ну, КМК, стоит увидеть живой код.

            match event.get():
                case Click(position=(x, y)):
                    handle_click_at(x, y)
                case KeyPress(key_name="Q") | Quit():
                    game.quit()
                case KeyPress(key_name="up arrow"):
                    game.go_north()
                ...
                case KeyPress():
                    pass # Ignore other keystrokes
                case other_event:
                    raise ValueError(f"Unrecognized event: {other_event}")

            Здесь все читается легче, чем описано в сухой документации, верно? (если я конечно правильно понял, о чем вы)


            1. danilovmy
              14.11.2022 11:29
              +3

              Так это ж тоже из документации. PEP 636 – Structural Pattern Matching: Tutorial.

              По мне, приведенный пример не читается легче.И могу обьяснить почему: В этой конструкции языка используется запутывающий синтаксис. KeyPress(key_name="Q") - в питоне стандартом это инициирование обьекта. KeyPress(key_name="Q") | Quit() это вызов '__or__' объектов. Но только не для pattern matching.

              Это не значит, что это плохо.

              Да, я привыкну со временем, что создание класса в конструкции case - это не создание класса, а проверка "pattern arguments" передаваемого объекта. Лично мне не нравится то, что в этой локальной области когнитивная сложность кода возрастает. Я приводил запутывающие примеры реального кода на докладе на Pycon DE 2022, где причиной роста сложности понимания был именно Pattern Matching. Спасибо Григорию Петрову за возможность сделать этот доклад и за помощь в подготовке.


      1. Pfinash
        13.11.2022 11:21

        Кстати в match поддерживается распаковка последовательностей и сопоставление объектов (по классу и значениям полей)


      1. youlose
        14.11.2022 12:48

        Мне кажется что вы путаете Pattern Mathing и Conditional Statements. Pattern Matching про сравнение одной структуры данных с другой и не важно что потом произойдёт. Switch/case это про выбор ветки с кодом, основываясь на выполнении условия и не важно как именно он сравнит паттерн матчингом или <, >, ==.

        К примеру в языке Elixir в котором Pattern Matching был изначально можно писать и так:

        defp add_is_trigger_to_options(question, %{task_id: task_id, question_type: :TRIGGER}) do

         // код

        end

        defp add_is_trigger_to_options(question, nil) do

         // другой код

        end

        и вот так:

        defp add_is_trigger_to_options(question, task) do

          case task do

            nil -> // другой код

            %{task_id: task_id, question_type: :TRIGGER} -> // код

          end

        end

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


  1. DmitryDavis
    13.11.2022 12:48
    +1

    Кроме абстрактных классов сейчас в питоне есть typing.Protocol, который больше похож на интерфейсы в других языках


    1. Tishka17
      15.11.2022 09:50

      Даже лучше соответствует определению интерфейса, так как не заставляет указывать что вы его реализуете (в отличие от джавы)


  1. teror4uks
    13.11.2022 16:46
    +6

    Про "нет интерфейсов" это конечно сильное заявление. Я уж молчу про Протоколы и Дженерики. Но чем "__iter__" , "__len__" , "__str__", etc, не интерфейсы? Реализация любых из этих интерфейсов даёт возможности использовать стандартные конструкции и builtin функции для взаимодействия с объектами, будь то итерция или доступ к значениям через словарные скобки, сравнение, и т.д.

    Автору явно надо углубить свои знания по питону прежде чем писать такое.


  1. SergeAx
    13.11.2022 17:25
    +2

    Вообще ООП возникло как средство упрощения разработки больших программных продуктов, в основном улучшения модульности. Если в условном C (чтобы было ближе к обсуждаемым временам) мне надо было писать #include somelib.h, а потом дёргать подключенные функции, передавая им на вход сконструированные разработчиком библиотеки типы, то в ООП вместо этого кастомные типы и функции для их обработки собраны в объекты. То, что объекты ООП сопоставимы с объектами реального мира - побочное явление, и нельзя сказать, что этого не было до ООП. Я могу декларировать тип struct duck { int age; bool gender}, и затем экспортировать из библиотеки функции void quack(d duck); void fly(d duck);

    Проблема с таким подходом в том, что я показываю всему миру внутренности duck и, что ещё хуже, позволяю их модифицировать. Проблема тут не в дисциплине или осознанности разработчика, а в том, что у меня нет способа сказать пользователю своей библиотеки, что можно трогать, а что нельзя. Также я не мог сказать, какие функции библиотеки предназначены для внешнего использования, а какие нет (static появилось позже) Обернуть это всё в объект - способ сократить размер API, предоставляемого библиотекой, а значит упростить жизнь пользователя и разработку новых версий и миграцию на них - нужно поддерживать меньше совместимости.


    1. GothicJS
      13.11.2022 23:54
      +1

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

      То есть пользователем некоего кода является другой код - клиентский, но пишет то его человек, вполне осознанно обращаясь к методам по их названиям.

      И тут нужно задаться вопросом - в каких вообще случаях человек неосознанно, ошибочно может обратиться к закрытому методу?

      В случае "тру оопшных языков" по идее только тогда, когда он тупо перепутал названия? И ЯП выдаст ему ошибку - мол вот тебе таблетка для памяти, запрещено.

      А в случае с пайтоном? Как вообще можно неосознанно обратиться к закрытым методам, зная, что в языке принято обозначать их нижним подчеркиванием? Никак.

      То есть получается, что в пайтоне то наружу ничего и не торчит.
      Рассуждаю в меру своего понимания, поправьте, если не прав.