Перейти к содержимому

Какие парадигмы и стили программирования поддерживает python

  • автор:

Какие парадигмы и стили программирования поддерживает Python ?

Какие парадигмы и стили программирования поддерживает Python?

Какие парадигмы и стили программирования Python поддерживает?

Какие парадигмы и стили программирования Python поддерживает?

Какие парадигмы Python не поддерживает?

Какие кодировки исходного текста программы поддерживает интерпретатор Python?

Какие характеристики можно отнести к языку программирования Python?

Какие характеристики можно отнести к языку программирования Python?

Какие характеристики можно отнести к языку программирования Python?

Какие характеристики можно отнести к языку программирования Python?

«Забытые» парадигмы программирования

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

Ладно. Введение это очень весело, но вы его все равно не читаете, так что кому интересно — добро пожаловать под кат!

Императивное программирование

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

Это были машинные коды, языки ассемблера и ранние высокоуровневые языки, вроде Fortran.

Ключевые моменты:

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

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

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

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

Основные понятия:
Порожденные понятия:

— Присваивание
— Переход
— Память
— Указатель

Языки поддерживающие данную парадигму:
Как основную:

— Языки ассемблера
— Fortran
— Algol
— Cobol
— Pascal
— C
— C++
— Ada

Как вспомогательную:

— Python
— Ruby
— Java
— C#
— PHP
— Haskell (через монады)

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

Структурное программирование

Структурное программирование — парадигма программирования (также часто встречающееся определение — методология разработки), которая была первым большим шагом в развитии программирования.

Основоположниками структурного программирования были такие знаменитые люди как Э. Дейкстра и Н. Вирт.

Языками-первопроходцами в этой парадигме были Fortran, Algol и B, позже их приемниками стали Pascal и C.

Ключевые моменты:

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

В структурном программировании мы по прежнему оперируем состоянием и инструкциями, однако вводится понятие составной инструкции (блока), инструкций ветвления и цикла.

Благодаря этим простым изменениям возможно отказаться от оператора goto в большинстве случаев, что упрощает код.

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

Основные понятия:

— Блок
— Цикл
— Ветвление

Языки поддерживающие данную парадигму:
Как основную:

— C
— Pascal
— Basic

Как вспомогательную:

— C#
— Java
— Python
— Ruby
— JavaScript

Поддерживают частично:
— Некоторые макроассемблеры (через макросы)

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

Процедурное программирование

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

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

Этим понятием на этот раз была процедура.

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

Ключевые моменты:

Процедура — самостоятельный участок кода, который можно выполнить как одну инструкцию.

В современном программировании процедура может иметь несколько точек выхода (return в C-подобных языках), несколько точек входа (с помощью yield в Python или статических локальных переменных в C++), иметь аргументы, возвращать значение как результат своего выполнения, быть перегруженной по количеству или типу параметров и много чего еще.

Основные понятия:
Порожденные понятия:

— Вызов
— Аргументы
— Возврат
— Рекурсия
— Перегрузка

Языки поддерживающие данную парадигму:
Как основную:

— C
— C++
— Pascal
— Object Pascal

Как вспомогательную:

— C#
— Java
— Ruby
— Python
— JavaScript

Поддерживают частично:
— Ранний Basic

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

Модульное программирование

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

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

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

Благодаря модулям впервые в программировании появилась серьезная инкапсуляция — возможно использовать какие-либо сущности внутри модуля, но не показывать их внешнему миру.

Ключевые моменты:

Модуль — это отдельная именованная сущность программы, которая объединяет в себе другие программные единицы, близкие по функциональности.

Например файл List.mod включающий в себя класс List
и функции для работы с ним — модуль.

Папка Geometry, содержащая модули Shape, Rectangle и Triangle — тоже модуль, хоть и некоторые языки разделяют понятие модуля и пакета (в таких языках пакет — набор модулей и/или набор других пакетов).

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

Основные понятия:
Порожденные понятия:
Языки поддерживающие данную парадигму:
Как основную:

— Haskell
— Pascal
— Python

Как вспомогательную:

— Java
— C#
— ActionScript 3

Поддерживают частично:
— C/C++

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

Вместо заключения

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

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

  • парадигмы программирования
  • программирование
  • императивное программирование
  • структурное программирование
  • процедурное программирование
  • Веб-разработка
  • Программирование
  • Совершенный код

Функциональный и процедурный подход — Python: Декларативное программирование

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

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

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

Процедурное решение

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

INPUT = [1, 2, 5, 12, 3, 5, 2, 7, 12] def main(): numbers = INPUT[:] filter_and_sort(numbers) # Сортируем и фильтруем по месту for number in numbers: print(number) # Выводим поэлементно в цикле def filter_and_sort(values): values.sort() # Список сортируется по месту previous_value = None index = 0 while index  len(values): value = values[index] if value == previous_value and index > 0: # Элемент удаляется из списка, то есть список опять модифицируется values.pop(index) else: index += 1 previous_value = value 

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

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

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

Функциональное решение

Напишем функциональный вариант с элементами декларативного стиля:

INPUT = [1, 2, 5, 12, 3, 5, 2, 7, 12] def main(): print('\n'.join(map(str, sorted(set(INPUT))))) 

Код описывает, какой результат мы хотим получить:

  • print() — напечатанное
  • ‘\n’.join(. ) — объединение через перевод строки
  • map(str, . ) — последовательность строк
  • sorted(set(. )) — полученных из отсортированного множества исходных чисел

Обратите внимание, что в коде нет ни одной переменной. Ничего не нужно защитно копировать, и самого кода гораздо меньше.

Попробуем проанализировать, как этот код работает:

  • Создается промежуточное множество set()
  • Внутри sorted() создается список — не обычный list() , но все равно копия
  • Для каждого итогового числа будет создано по строке
  • Функция ‘\n’.join() соберет строку, размер которой будет равен сумме длин всех строк с числами и количеству переводов строк

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

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

Истина где-то посередине

Функциональное решение читается хорошо, если разработчик в принципе знаком с таким стилем. Читаемость кода — важная характеристика, поэтому при небольшом объеме входных данных можно выбирать такой вариант.

Процедурное решение читается достаточно тяжело: нужно буквально выполнять код в уме. Еще в такой код сложнее вносить изменения — он слишком специфичен и завязан на текущую задачу. А еще нужно помнить, что процедура filter_and_sort() модифицирует свой аргумент.

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

Например, в функциональном решении можно применить цикл:

def main(): for number in sorted(set(INPUT)): print(number) 

Этот код не создает промежуточных строк, потому что команда print() и так умеет выводить числа. Большая строка не склеивается перед выводом — это самая заметная экономия.

Усложним ситуацию и представим, что все входные элементы уникальны. В таком случае множество будет копией исходного списка — внутри sorted() будет еще одна копия. В итоге у нас будет две копии.

Посмотрим, как еще можно улучшить императивный вариант:

def main(): previous_value = None for value in sorted(INPUT): if previous_value is None or value != previous_value: previous_value = value print(value) 

Открыть доступ

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

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов

Наши выпускники работают в компаниях:

Python Стили программирования — выбираю подходящие.

Пламенный привет посетителям этой страницы, пришедшим из социальных сетей! С апреля 2021-го года наблюдаю удивительное явление: обильный поток посетителей из 4-х социальных сетей. В связи с этим настоятельно рекомендую всем неоднократно и регулярно посещать сайт rtbsm.ru — там в общих чертах изложена Российская Теннисная Балльная Система Марии (Шараповой).

Python Стили программирования — мне известны три основных стиля программирования: Процедурный, Объектно-ориентированный, Функциональный и Структурный.

Процедурный Стиль программирования — это программирование, основанное на использовании процедур:

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

Процедурное программирование является отражением архитектуры традиционных ЭВМ, которая была предложена Фон Нейманом в 1940-х годах.

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

Основные сведения

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

Таким образом, с точки зрения программиста имеются программа и память, причём первая последовательно обновляет содержимое последней.

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

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

Привожу разъяснение особенностей императивных языков программирования:

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

Объектно-ориентированный Стиль программирования — это стиль, который удовлетворяет трём изложенным ниже требованиям:

  • Необходимо обратить внимание на следующие важные части этого определения:
    • 1) объектно-ориентированное программирование использует в качестве основных логических конструктивных элементов объекты, а не алгоритмы;
    • 2) каждый объект является экземпляром определенного класса;
    • 3) классы образуют иерархии.

    Основные понятия

    Абстракция данных

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

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

    Инкапсуляция — свойство системы, позволяющее объединить данные и методы, работающие с ними, в классе. Одни языки (например, С++, Java или Ruby) отождествляют инкапсуляцию с сокрытием, но другие (Smalltalk, Eiffel, OCaml) различают эти понятия.

    Наследование

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

    Полиморфизм подтипов

    Полиморфизм подтипов (в ООП называемый просто «полиморфизмом») — свойство системы, позволяющее использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта. Другой вид полиморфизма — параметрический — в ООП называют обобщённым программированием.

    Класс

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

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

    Эти блоки называются «свойствами» и почти совпадают по конкретному имени со своим полем (например, имя поля может начинаться со строчной, а имя свойства – с заглавной буквы).

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

    Переменная-объект, относящаяся к заданному классом типу, называется экземпляром этого класса.

    При этом в некоторых исполняющих системах класс также может представляться некоторым объектом при выполнении программы посредством динамической идентификации типа данных.

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

    В свою очередь, целостность предметной области объектов и их интерфейсов, а также удобство их проектирования, обеспечивается наследованием.

    Объект

    Сущность в адресном пространстве вычислительной системы, появляющаяся при создании экземпляра класса (например, после запуска результатов компиляции и связывания исходного кода на выполнение).

    Функциональный Стиль программирования подробно описан в таком тексте:

    Что такое функциональное программирование?

    • Функции — объекты первого класса. Т. е. всё, что можно делать с «данными», можно делать и с функциями (вроде передачи функции другой функции в качестве параметра).
    • Использование рекурсии в качестве основной структуры контроля потока управления. В некоторых языках не существует иной конструкции цикла, кроме рекурсии.
    • Акцент на обработке списков (lists, отсюда название Lisp — LISt Processing). Списки с рекурсивным обходом подсписков часто используются в качестве замены циклов.
    • «Чистые» функциональные языки избегают побочных эффектов. Это исключает почти повсеместно распространенный в императивных языках подход, при котором одной и той же переменной последовательно присваиваются различные значения для отслеживания состояния программы.
    • FP не одобряет или совершенно запрещает утверждения (statements), используя вместо этого вычисление выражений (т. е. функций с аргументами). В предельном случае одна программа есть одно выражение (плюс дополнительные определения).
    • FP акцентируется на том, что должно быть вычислено, а не как.
    • Большая часть FP использует функции «высокого порядка» (функции, оперирующие функциями, оперирующими функциями).

    Структурный стиль программирования:

    Структурное программирование — методология разработки программного обеспечения, в основе которой лежит представление программы в виде иерархической структуры блоков. Предложена в 1970-х годах Э. Дейкстрой и др.

    В соответствии с данной методологией любая программа строится без использования оператора goto из трёх базовых управляющих структур: последовательность, ветвление, цикл; кроме того, используются подпрограммы. При этом разработка программы ведётся пошагово, методом «сверху вниз».

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

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

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

    Методология структурной разработки программного обеспечения была признана «самой сильной формализацией 70-х годов».

    По мнению Бертрана Мейера, «Революция во взглядах на программирование, начатая Дейкстрой, привела к движению, известному как структурное программирование, которое предложило систематический, рациональный подход к конструированию программ.

    Структурное программирование стало основой всего, что сделано в методологии программирования, включая и объектное программирование».

    Подробная информация про Структурное программирование содержится на странице Python Структурное программирование.

    Python Стили программирования — это и Процедурный, и Объектно-ориентированный, и Функциональный, и Структурный стили программирования, ибо Python допускает использование всех четырёх стилей программирования.

    Привожу информацию, наглядно показывающую разницу между императивным и функциональным стилями программирования:

    • Рефал (для этой категории, представленной единственным языком, нет общепринятого названия);
    • Аппликативные (Лисп, ML, Tcl, Rebol);
    • Комбинаторные (APL/J/K, FP/FL);
    • Бесточечные (чистые конкатенативные) (Joy, Cat, Factor, подмножество PostScript).

    Чтобы ещё больше запудрить Вам мозги, привожу информацию об Основных моделях программирования, а также о Подходах и приёмах:

    Основные модели программирования

    • Императивное программирование
    • Декларативное программирование
    • Структурное программирование
    • Функциональное программирование
    • Логическое программирование
    • Объектно-ориентированное программирование
      • Программирование, основанное на классах
      • Программирование, основанное на прототипах
      • Субъектно-ориентированное программирование

      Подходы и приёмы

      • Структурное программирование
      • Процедурное программирование
      • Аппликативное программирование
      • Обобщённое программирование
      • Доказательное программирование
      • Порождающее программирование
      • Аспектно-ориентированное программирование
      • Агентно-ориентированное программирование
      • Рекурсия
      • Автоматное программирование
      • Событийно-ориентированное программирование
      • Компонентно-ориентированное программирование
      • Грамотное программирование

      Чтобы разобраться во всех особенностях современных методов, подходов и приёмов программирования, нужно годами заниматься программированием профессионально и сильно перестроить своё мышление.

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

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

      Python Стили программирования

      И не забывайте, пожалуйста, нажимать на кнопки социальных сетей, которые расположены под текстом каждой страницы сайта.
      Продолжение тут…

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *