Функциональное программирование на языке Python


Оглавление (нажмите, чтобы открыть):

Функциональное программирование на языке Python

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

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

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

Теория в теории

Как и в разговоре об ООП, так и о функциональном программировании, мы стараемся избегать определений. Все-таки четкое определение дать тяжело, поэтому здесь четкого определения не будет. Однако! Хотелки для функционального языка выделим:

  • Функции высшего порядка
  • Чистые функции
  • Иммутабельные данные

Это не полный список, но даже этого хватает чтобы сделать сделать «красиво». Если читателю хочется больше, то вот расширенный список:

  • Функции высшего порядка
  • Чистые функции
  • Иммутабельные данные
  • Замыкания
  • Ленивость
  • Хвостовая рекурсия
  • Алгебраические типы данных
  • Pattern matching

Постепенно рассмотрим все эти моменты и как использовать в Python.

А сегодня кратко, что есть что в первом списке.

Чистые функции

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

  • Легче читать и понимать код
  • Легче тестировать (не надо создавать «условий»)
  • Надежнее, потому что не зависят от «погоды» и состояния окружения, только от аргументов
  • Можно запускать параллельно, можно кешировать результат

Иммутабельные данные

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

Преимущества неизменяемых структур:

  • Безопасно разделять ссылку между потоками
  • Легко тестировать
  • Легко отследить жизненный цикл (соответствует data flow)

Функции высшего порядка

Функцию, принимающую другую функцию в качестве аргумента и/или возвращающую другую функцию, называют функцией высшего порядка:

Рассмотрели теорию, начнем переходить к практике, от простого к сложному.

Списковые включения или генератор списка

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

Цикл с условием, подобные встречаются не редко. А теперь попробуем эти 5 строк превратить в одну:

Недурно, 5 строк или 1. Причем выразительность повысилась и такой код проще понимать — один комментарий можно на всякий случай добавить.

В общем виде эта конструкция такова:

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

Анонимные функции или lambda

Продолжаем сокращать количества кода.

Функция короткая, а как минимум 2 строки потратили. Можно ли сократить такие маленькие функции? А может не оформлять в виде функций? Ведь, не всегда хочется плодить лишние функции в модуле. А если функция занимает одну строчку, то и подавно. Поэтому в языках программирования встречаются анонимные функции, которые не имеют названия.

Анонимные функции в Python реализуются с помощью лямбда-исчисления и выглядят как лямбда-выражения:

Для программиста это такие же функции и с ними можно также работать.

Чтобы обращаться к анонимным функциям несколько раз, присваиваем переменной и пользуемся на здоровье.

Лямбда-функции могут выступать в качестве аргумента. Даже для других лямбд:

Использование lambda

Функции без названия научились создавать, а где использовать сейчас узнаем. Стандартная библиотека предоставляет несколько функций, которые могут принимать в качестве аргумента функцию — map(), filter(), reduce(), apply().

Функция map() обрабатывает одну или несколько последовательностей с помощью заданной функции.

Мы уже познакомились с генератором списков, давайте и воспользуемся если длина список одинаковая):

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

filter()

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

То же самое с помощью списковых выражений:

reduce()

Для организации цепочечных вычислений в списке можно использовать функцию reduce(). Например, произведение элементов списка может быть вычислено так (Python 2):

Вычисления происходят в следующем порядке:

Цепочка вызовов связывается с помощью промежуточного результата (res). Если список пустой, просто используется третий параметр (в случае произведения нуля множителей это 1):

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

Для наиболее распространенных операций в Python есть встроенные функции:

В Python 3 встроенной функции reduce() нет, но её можно найти в модуле functools.

apply()

Функция для применения другой функции к позиционным и именованным аргументам, заданным списком и словарем соответственно (Python 2):

В Python 3 вместо функции apply() следует использовать специальный синтаксис:

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

Замыкания

Функции, определяемые внутри других функций, представляют собой замыкания. Зачем это нужно? Рассмотрим пример, который объяснит:

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

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

Научимся оформлять замыкания:

Заключение

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

С чего начать программирование на Python

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

Что такое программирование на Python?

Перед началом познакомиться с самим языком.
Python — язык общего назначения. Имеет приложения разных направлений: веб-разработки (например, Django и Bottle ), научных и математических вычислений ( Orange, SymPy, NumPy ) для настольных графических пользовательских интерфейсов ( Pygame, Panda3D ).

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

История Python

Python старый язык, созданный Гвидо Ван Россумом. Разработка началась в конце 1980-х., и в феврале 1991 года вышла первая версия.


Зачем создан Python?
В конце 1980-ых, Гвидо Ван Россум работал над группой операционных систем Amoeba. Он хотел использовать интерпретируемый язык, такой как ABC (у ABC простой и доступный в понимании синтаксис), который мог бы получить доступ к системным вызовам Amoeba. Поэтому он решил создать масштабируемый язык. Это привело к созданию нового языка, у которого позже появилось название Python.

Почему выбрали Python
Нет. Он не назван в честь опасной змеи. Россум был фанатом комедийного сериала в конце 70-х. Название “Python” было взято из этого же сериала “Monty Python’s Flying Circus” (Летающий цирк Монти Пайтона).

Дата выпуска версий языка

Версия Дата выпуска
Python 1.0 (первый стандартный выпуск) Python 1.6 (последняя выпущенная версия) Январь 1994
Сентябрь 5, 2000
Python 2.0 (представлены списки) Python 2.7 (последняя выпущенная версия) Октябрь 16, 2000
Июль 3, 2010
Python 3.0 (Сделан акцент на удаление дублирующих конструкций и модулей) Python 3.7 (Последняя обновленная версия) Декабрь 3, 2008
настоящее время

Особенности программирования на Python

  1. Простой язык, легкий и доступный в изучении
    У Python читаемый синтаксис. Гораздо проще читать и писать программы на Python по сравнению с другими языками, такими как: C++, Java, C# . Python делает программирование интересным и позволяет сфокусироваться на решении, а не синтаксисе.
    Для новичков, отличный выбором — начать изучение с Python.
  2. Бесплатный и с открытым кодом
    Можно свободно использовать и распространять программное обеспечение, написанное на Python, даже для коммерческого использования. Вносить изменения в исходный код Python.
    Над Python работает большое сообщество, постоянно совершенствуя язык в каждой новой версии.
  3. Портативность
    Перемещайте и запускайте программы на Python из одной платформы на другую без каких-либо изменений.
    Код работает практически на всех платформах, включая Windows, Mac OS X и Linux.
  4. Масштабируемый и встраиваемый
    Предположим, что приложение требует повышения производительности. Вы можете с легкостью комбинировать фрагменты кода на C/C++ и других языках вместе с кодом Python.
    Это повысит производительность приложения, а также дает возможность написания скриптов, создание которых на других языках требует больше настроек и времени.
  5. Высокоуровневый, интерпретируемый язык
    В отличии от C/C++ , вам не нужно беспокоиться о таких сложных задачах, как “сборка мусора” или управление памятью.
    Так же, когда вы запускаете код Python, он автоматически преобразует ваш код в язык, который понимает компьютер. Не нужно думать об операциях более низкого уровня.
  6. Стандартные библиотеки для решения общих задач
    Python укомплектован рядом стандартных библиотек, что облегчает жизнь программиста, так как нет необходимости писать весь код самостоятельно. Например, что бы подключить базу данных MySQL на Web сервер, используйте библиотеку MySQLdb , добавляя ее строкой import MySQLdb .
    Стандартные библиотеки в Python протестированы и используются сотнями людей. Поэтому будьте уверенны, они не нарушит работу приложения.
  7. Объектно-ориентированный
    В Python все объект. Объектно-ориентированное программирование (ООП) помогает решить сложную проблему интуитивно.
    Разделяйте сложные задачи на маленькие части, создавая объекты.

Приложения на Python

Веб-приложения
Создание масштабируемых веб-приложений (Web Apps), с помощью фреймворков и CMS (Система управления содержимым), созданных на Python. Популярные платформы для создания Web приложений: Django, Flask, Pyramid, Plone, Django CMS .
Сайты, такие как Mozilla, Reddit, Instagram и PBS написаны на Python.

Научные и цифровые вычисления
У Python много библиотек для научных и математических вычислений. Есть библиотеки, такие как: SciPy и NumPy которые используются для общих вычислений. И специальные библиотеки, такие как: EarthPy для науки о Земле, AstroPy для астрономии и так далее.
Также, язык часто используется в машинном обучении, анализе и сборе данных.

Создание прототипов программного обеспечения
Python медленный, в сравнении с компилированными языками, такими как C++ и Java. Это не очень практичный выбор, если ресурсы ограничены и при этом нужна максимальная эффективность.
Тем не менее, Python — прекрасный язык для создания прототипов. Используйте Pygame (библиотека для создания игр), чтобы создать для начала прототип игры. Если прототип понравился, используйте язык C++ для создания реальной игры.

Тест на знание python

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

4 причины выбрать Python в качестве первого языка

  1. Простой элегантный синтаксис
    Программировать на Python интересно. Легче понять и написать код на Python. Почему? Синтаксис кажется естественным и простым. Возьмите этот код для примера:

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

  • Не слишком строгий
    Не нужно определять тип переменной в Python. Нет необходимости добавлять “;” в конце строки.
    Python принуждает следовать методам написания читаемого кода (например, одинаковым отступам). Эти мелочи могут значительно облегчить обучение новичкам.
  • Выразительность языка
    Python позволяет писать программы с большей функциональностью и с меньшим количеством строк кода. Вот ссылка на исходный код игры Tic-tac-toe с графическим интерфейсом и противником в лице смарт-компьютера менее чем на 500 строк кода. Это просто пример. Вы будете удивлены, как много можно сделать с Python, как только изучите основы языка.
  • Большое сообщество и поддержка
    У Python большое сообщество с огромной поддержкой. Множество активных форумов в интернете, которые помогут, когда возникают вопросы. Вот некоторые из них:
    • Python на Хабре
    • Вопросы о Python на Тостер
    • Вопросы о Python на Stack Overflow
  • Первая программа на Python

    Часто программа, которая называется “Hello, World!” используется для демонстрации языка программирования новичкам. “Hello, World!” это простая программа, которая выводит “Hello, World!”

    Python — один из простейших языков для изучения и создание программы “Hello, World!” такое же простое, введите print(«Hello, World!») . Поэтому, мы напишем другую программу.

    Программа сложения двух чисел

    Как работает эта программа?

    Строка 1: # Сложите два числа
    Строка, начинающаяся с # в программировании на Python — комментарий.
    Комментарии используются для описания цели строки кода. Это поможет вам, так же как и другим программистам понять смысл кода. Они игнорируются компиляторами и интерпретаторами.

    Строка 2: num1 = 3
    Здесь, num1 — переменная. Вы можете сохранять значение в переменной. В этом случае, 3 сохраняется в переменной.

    Строка 3: num2 = 5
    Аналогично, 5 сохраняется в переменной num2 .

    Строка 4: sum = num1 + num2
    Переменная num2 прибавляется к num1 с помощью оператора + . Результат сложения сохраняется в другой переменной sum .

    Строка 5: print(sum)
    Функция print() выводит результат на экран. В нашем случае, она выводит на экран 8.

    Важные вещи, о которых следует помнить.

    Для представления инструкции в Python, используется новая строка (enter). Использование “;” в конце утверждения не требуется (в отличии C/C++, JavaScript, PHP ).
    Вместо фигурных скобок < >, используются отступы (4 пробела) для перехода на новый блок.

    Научитесь самостоятельно программировать на Python

    Изучите Python с помощью PythonRU.com

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

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

    Рекомендуемые книги

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

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

    Обложка Описание
    Изучаем Python
    Четвертое издание «Изучаем Python» – это учебник, написанный доступным языком, рассчитанный на индивидуальную скорость обучения. В книге представлены основные типы объектов в языке Python, порядок их создания и работы с ними, а также функции как основной процедурный элемент языка.
    Программирование на Python 3. Подробное руководство
    Автор начинает с описания ключевых элементов Python, знание которых необходимо в качестве базовых понятий. Затем обсуждаются более сложные темы, поданные так, чтобы читатель мог постепенно наращивать свой опыт: распределение вычислительной нагрузки между несколькими процессами и потоками, использование сложных типов данных, управляющих структур и функций, создание приложений для работы с базами данных SQL и с файлами DBM.
    Python и анализ данных
    Книгу можно рассматривать как современное практическое введение в разработку научных приложений на Python, ориентированных на обработку данных. Описаны те части языка Python и библиотеки для него, которые необходимы для эффективного решения широкого круга аналитических задач: интерактивная оболочка IPython, библиотеки NumPy и pandas, библиотека для визуализации данных matplotlib и др.
    Python для детей и родителей. Играй и программируй
    Научите своих детей программировать уже сейчас с помощью этой книги! В книге представлен язык Python, один из самых популярных и простых. Вы найдете здесь много упражнений – полезных, интересных и забавных, поэтому ваш ребенок не заскучает. Материал написан доступно и просто, поэтому ему не составит труда освоить азы программирования.

    Python — потрясающий язык. Синтаксис настолько прост, и длина кода настолько коротка, что делает его понятным и легким в написании.
    Если вы только начинаете программировать, Python— отличный выбор. Вы будете удивлены тому, сколько задач решает Python как только изучите его основы.
    Легко упустить из виду факт, что Python — мощный язык. Хорош для обучения программированию. Воплотите свою идею, создайте игру или начните с Data Science, Python поможет во всем, чтобы вы не затеяли.

    Введение в программирование на языке Python

    Что такое Python?

    О Python (лучше произносить «питон», хотя некоторые говорят «пайтон») — предмете данного изучения, лучше всего говорит создатель этого языка программирования, голландец Гвидо ван Россум:

    «Python — интерпретируемый, объектно-ориентированный высокоуровневый язык программирования с динамической семантикой. Встроенные высокоуровневые структуры данных в сочетании с динамической типизацией и связыванием делают язык привлекательным для быстрой разработки приложений ( RAD , Rapid Application Development ). Кроме того, его можно использовать в качестве сценарного языка для связи программных компонентов. Синтаксис Python прост в изучении, в нем придается особое значение читаемости кода, а это сокращает затраты на сопровождение программных продуктов. Python поддерживает модули и пакеты, поощряя модульность и повторное использование кода. Интерпретатор Python и большая стандартная библиотека доступны бесплатно в виде исходных и исполняемых кодов для всех основных платформ и могут свободно распространяться.»

    В процессе изучения будет раскрыт смысл этого определения, а сейчас достаточно знать, что Python — это универсальный язык программирования. Он имеет свои преимущества и недостатки, а также сферы применения. В поставку Python входит обширная стандартная библиотека для решения широкого круга задач. В Интернете доступны качественные библиотеки для Python по различным предметным областям: средства обработки текстов и технологии Интернет, обработка изображений, инструменты для создания приложений, механизмы доступа к базам данных, пакеты для научных вычислений, библиотеки построения графического интерфейса и т.п. Кроме того, Python имеет достаточно простые средства для интеграции с языками C, C++ (и Java) как путем встраивания (embedding) интерпретатора в программы на этих языках, так и наоборот, посредством использования библиотек, написанных на этих языках, в Python-программах. Язык Python поддерживает несколько парадигм программирования: императивное (процедурный, структурный, модульный подходы), объектно-ориентированное и функциональное программирование.

    Можно считать, что Python — это целая технология для создания программных продуктов (и их прототипов). Она доступна почти на всех современных платформах (как 32-битных, так и на 64-битных) с компилятором C и на платформе Java.

    Может показаться, что, в программной индустрии нет места для чего-то другого кроме C/C++, Java, Visual Basic, C#. Однако это не так. Возможно, благодаря данному курсу лекций и практических занятий у Python появятся новые приверженцы, для которых он станет незаменимым инструментом.

    Как описать язык?

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

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

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

    История языка Python

    Создание Python было начато Гвидо ван Россумом (Gu >van Rossum) в 1991 году, когда он работал над распределенной ОС Амеба. Ему требовался расширяемый язык, который бы обеспечил поддержку системных вызовов. За основу были взяты ABC и Модула-3. В качестве названия он выбрал Python в честь комедийных серий BBC «Летающий цирк Монти-Пайтона», а вовсе не по названию змеи. С тех пор Python развивался при поддержке тех организаций, в которых Гвидо работал. Особенно активно язык совершенствуется в настоящее время, когда над ним работает не только команда создателей, но и целое сообщество программистов со всего мира. И все-таки последнее слово о направлении развития языка остается за Гвидо ван Россумом.

    Функциональное программирование на языке Python

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

    Что такое Python?
    Python — свободно распространяемый, очень высокоуровневый интерпретируемый язык, разработанный Гвидо ван Россумом (Guido van Rossum). Он сочетает прозрачный синтаксис с мощной (но необязательной) объектно-ориентированной семантикой. Python доступен почти на всех существующих ныне платформах и обладает очень высокой переносимостью между платформами.

    Что такое функциональное программирование?
    Лучше всего начать с труднейшего вопроса — а что, собственно, такое «функциональное программирование (FP)»? Один из возможных ответов — «это когда вы пишете на языке наподобие Lisp, Scheme, Haskell, ML, OCAML, Clean, Mercury или Erlang (или еще на некоторых других)». Этот ответ, безусловно, верен, но не сильно проясняет суть. К сожалению, получить четкое мнение о том, что же такое FP, оказывается очень трудно даже среди собственно функциональных программистов. Вспоминается притча о трех слепцах и слоне. Возможно также определить FP, противопоставив его «императивному программированию» (тому, что вы делаете на языках наподобие C, Pascal, C++, Java, Perl, Awk, TCL и на многих других — по крайнее мере, большей частью).

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

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


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

    Функциональные возможности, присущие Python
    Python поддерживает большую часть характеристик функционального программирования, начиная с версии Python 1.0. Но, как большинство возможностей Python, они присутствуют в очень смешанном языке. Так же как и с объектно-ориентированными возможностями Python, вы можете использовать то, что вам нужно, и игнорировать все остальное (пока оно вам не понадобится). В Python 2.0 было добавлено очень удачное «синтаксическое украшение» — списочные встраивания (list comprehensions). Хотя и не добавляя принципиально новых возможностей, списочные встраивания делают использование многих старых возможностей значительно приятнее.

    Базовые элементы FP в Python — функции map(), reduce(), filter() и оператор lambda. В Python 1.x введена также функция apply(), удобная для прямого применения функции к списку, возвращаемому другой. Python 2.0 предоставляет для этого улучшенный синтаксис. Несколько неожиданно, но этих функций и всего нескольких базовых операторов почти достаточно для написания любой программы на Python; в частности, все управляющие утверждения (‘if’, ‘elif’, ‘else’, ‘assert’, ‘try’, ‘except’, ‘finally’, ‘for’, ‘break’, ‘continue’, ‘while’, ‘def’) можно представить в функциональном стиле, используя исключительно функции и операторы. Несмотря на то, что задача реального удаления всех команд управления потоком, возможно, полезна только для представления на конкурс «невразумительный Python» (с кодом, выглядящим как программа на Lisp’е), стоит уяснить, как FP выражает управляющие структуры через вызовы функций и рекурсию.

    Исключение команд управления потоком
    Первое, о чем стоит вспомнить в нашем упражнении — то, что Python «замыкает накоротко» вычисление логических выражений.1 Оказывается, это предоставляет эквивалент блока ‘if’/’elif’/’else’ в виде выражения. Итак:

    Казалось бы, наша версия условных вызовов с помощью выражений — не более, чем салонный фокус; однако все становится гораздо интересней, если учесть, что оператор lambda может содержать только выражения! Раз, как мы только что показали, выражения могут содержать условные блоки, используя короткое замыкание, выражение lambda позволяет в общей форме представить условные возвращаемые значения. Базируясь на предыдущем примере:

    Функции как объекты первого класса
    Приведенные примеры уже засвидетельствовали, хотя и неочевидным образом, статус функций как объектов первого класса в Python. Дело в том, что, создав объект функции оператором lambda, мы произвели чрезвычайно общее действие. Мы имели возможность привязать наш объект к именам pr и namenum в точности тем же способом, как могли бы привязать к этим именам число 23 или строку «spam». Но точно так же, как число 23 можно использовать, не привязывая ни к какому имени (например, как аргумент функции), мы можем использовать объект функции, созданный lambda, не привязывая ни к какому имени. Функция в Python — всего лишь еще одно значение, с которым можно что-то сделать.

    Главное, что мы делаем с нашими объектами первого класса — передаем их во встроенные функции map(), reduce() и filter(). Каждая из этих функций принимает объект функции в качестве первого аргумента. map() применяет переданную функцию к каждому элементу в переданном списке (списках) и возвращает список результатов. reduce() применяет переданную функцию к каждому значению в списке и ко внутреннему накопителю результата; например, reduce(lambda n,m:n*m, range(1,10)) означает 10! (факториал 10 — умножить каждый элемент на результат предыдущего умножения). filter() применяет переданную функцию к каждому элементу списка и возвращает список тех элементов исходного списка, для которых переданная функция вернула значение истинности. Мы также часто передаем функциональные объекты нашим собственным функциям, но чаще некоторым комбинациям вышеупомянутых встроенных функций.

    Комбинируя три этих встроенных FP-функции, можно реализовать неожиданно широкий диапазон операций потока управления, не прибегая к утверждениям (statements), а используя лишь выражения.

    Функциональные циклы в Python
    Замена циклов на выражения так же проста, как и замена условных блоков. ‘for’ может быть впрямую переведено в map(). Так же, как и с условным выполнением, нам понадобится упростить блок утверждений до одного вызова функции (мы близки к тому, чтобы научиться делать это в общем случае):

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

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

    Перевести ‘while’ впрямую немного сложнее, но вполне получается :

    Наш вариант ‘while’ все еще требует функцию while_block(), которая сама по себе может содержать не только выражения, но и утверждения (statements). Но мы могли бы продолжить дальнейшее исключение утверждений в этой функции (как, например, замену блока ‘if/else’ в вышеописанном шаблоне на короткозамкнутое выражение). К тому же, обычная проверка на месте (наподобие ‘while myvar==7’) вряд ли окажется полезной, поскольку тело цикла (в представленном виде) не может изменить какие-либо переменные (хотя глобальные переменные могут быть изменены в while_block()). Один из способов применить более полезное условие — заставить while_block() возвращать более осмысленное значение и сравнивать его с условием завершения. Стоит взглянуть на реальный пример исключения утверждений:

    Мы достигли того, что выразили небольшую программу, включающую ввод/вывод, циклы и условия в виде чистого выражения с рекурсией (фактически — в виде функционального объекта, который при необходимости может быть передан куда угодно). Мы все еще используем служебную функцию monadic_print(), но эта функция совершенно общая и может использоваться в любых функциональных выражениях , которые мы создадим позже (это однократные затраты).2 3 Заметьте, что любое выражение, содержащее monadic_print(x) вычисляется так же, как если бы оно содержало просто x. В FP (в частности, в Haskell) есть понятие «монады» для функции, которая «не делает ничего, и вызывает побочный эффект при выполнении».

    Исключение побочных эффектов
    После всей проделанной работы по избавлению от совершенно осмысленных конструкций и замене их на невразумительные вложенные выражения, возникает естественный вопрос — «Зачем?!». Перечитывая мои описания характеристик FP, мы можем видеть, что все они достигнуты в Python. Но важнейшая (и, скорее всего, в наибольшей степени реально используемая) характеристика — исключение побочных эффектов или, по крайней мере, ограничение их применения специальными областями наподобие монад. Огромный процент программных ошибок и главная проблема, требующая применения отладчиков, случается из-за того, что переменные получают неверные значения в процессе выполнения программы. Функциональное программирование обходит эту проблему, просто вовсе не присваивая значения переменным.

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

    Этот проект слишком мал для того, чтобы что-нибудь пошло не так. Но, возможно, он встроен в код, предназначенный для достижения множества других целей в то же самое время. Секции, комментированные как «#. прочий код. » — места, где побочные эффекты с наибольшей вероятностью могут привести к ошибкам. В любой из этих точек переменные xs, ys, bigmuls, x, y могут приобрести неожиданные значения в гипотетическом коде. Далее, после завершения этого куска кода все переменные могут иметь значения, которые могут ожидаются, а могут и не ожидаться посдедующим кодом. Очевидно, что инкапсуляция в функциях/объектах и тщательное управление областью видимости могут использоваться, чтобы защититься от этого рода проблем. Вы также можете всегда удалять (‘del’) ваши переменные после использования. Но, на практике, указанный тип ошибок весьма обычен.

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

    Мы связываем в примере анонимные (‘lambda’) функции с именами, но это не необходимо. Вместо этого мы могли просто вложить определения. Мы использовали имена как ради большей читаемости, так и потому, что combine() — в любом случае отличная служебная функция (генерирует список всех возможных пар элементов из двух списков). В свою очередь, dupelms() в основном лишь вспомогательная часть combine(). Хотя этот функциональный пример более многословен, чем императивный, при повторном использовании служебных функций код в собственно bigmuls() окажется, вероятно, более лаконичным, чем в императивном варианте.

    Реальное преимущество этого функционального примера в том, что в нем абсолютно ни одна переменная не меняет своего значения. Какое-либо неожиданное побочное влияние на последующий код (или со стороны предыдущего кода) просто невозможно. Конечно, само по себе отсутствие побочных эффектов не гарантирует безошибочность кода, но в любом случае это преимущество. Однако заметьте, что Python, в отличие от многих функциональных языков, не предотвращает повторное привязывание имен bigmuls, combine и dupelms. Если дальше в процессе выполнения программы combine() начнет значить что-нибудь другое — увы! Можно было бы разработать класс-одиночку (Singleton) для поддержки однократного связывания такого типа (напр. ‘s.bigmuls’, etc.), но это выходит за рамки настоящей статьи.

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

    Заключение
    Эта статья продемонстрировала способы замены практически любой конструкции управления потоком в Python на функциональный эквивалент (избавляясь при этом от побочных эффектов). Эффективный перевод конкретной программы требует дополнительного обдумывания, но мы увидели, что встроенные функциональные примитивы являются полными и общими. В последующих статьях мы рассмотрим более мощные подходы к функциональному программированию; и, я надеюсь, сможем подробнее рассмотреть «pro» и «contra» функционального подхода.

    Лабораторные работы ТГПУ

    Инструменты пользователя

    Инструменты сайта

    Боковая панель

    Содержание

    Содержание

    Введение

    Роль информатики в развитии общества чрезвычайно велика. Сегодня в мире нет ни одной отрасли науки и техники, которая развивалась бы столь же стремительно, как информатика. Каждый год происходит смена поколений аппаратных и программных средств вычислительной техники. Фактически за последние годы произошла революция в области передачи, накопления и обработки информации. Эта революция, затрагивает все области человеческой жизни. Значительное увеличение возможностей компьютерной техники, развитие информационных сетей, создание новых информационных технологий приводят к сильным изменениям во всех сферах общества: в производстве, науке, образовании, медицине и так далее. Народы развитых стран осознают, что совершенствование информационных технологий представляет самую важную, хотя дорогостоящую и трудную задачу (1).
    В связи с наблюдаемым в настоящее время стремительным развитием персональной вычислительной техники, происходит постепенное изменение требований, предъявляемых к языкам программирования. Все большую роль начинают играть интерпретируемые языки, поскольку возрастающая мощь персональных компьютеров начинает обеспечивать достаточную скорость выполнения интерпретируемых программ. А единственным существенным преимуществом компилируемых языков программирования является создаваемый ими высокоскоростной код. Когда скорость выполнения программы не является критичной величиной, наиболее правильным выбором будет интерпретируемый язык, как более простой и гибкий инструмент программирования.
    В связи с этим, определенный интерес представляет рассмотрение сравнительно нового языка программирования Python, который был создан его автором Гвидо ван Россумом в начале 90-х годов.
    Отличительные характеристики языка:

    Язык можно рекомендовать всем, кто только начинает программировать, как первый язык программирования в жизни.

    Цель курсовой работы

    Целью данной работы является: создание учебно — методического комплекса по изучению языка программирования Python.

    Язык программирования Python

    Python — современный язык программирования, работающий на всех распространенных операционных системах для настольных компьютеров. Язык программирования Питон разрабатывается чуть более 20 лет. В настоящее время активно используется две версии языка — более старая версия 2 и современная версия. Версия 2 более не развивается, но до сих пор еще используется, поскольку очень много программного обеспечения и библиотек разработано именно для версии 2. Между версиями есть существенная несовместимость, в том числе в синтаксисе команд ввода-вывода (программа на языке Python 2-й версии может не работать в 3-й версии и наоборот), но в целом они очень похожи. Мы будет использовать именно версию 3, как более современную и совершенную.
    Python — современный универсальный интерпретируемый язык программирования.
    Его достоинства:

    Установка интерпретатора
    Пример установки на Windows x64:
    1. Скачиваем дистрибутив Python3 с официального сайта python.org (рис. 1).

    2. Для установки дистрибутива дополнительных настроек не требуется, поэтому нажимаем Next на всех этапах установки (рис. 2).

    3. Дистрибутив установлен, чтобы проверить работу Python3, откроем командную строку Windows(Пуск > Выполнить > cmd) и в командной строке напишем python, если все нормально, то вы будете наблюдать следующий текст на экране (рис. 3).

    Напишем следующий код в командной строке:
    print(“Hello World. ”)
    Если все верно, то в консоль выведется “Hello World. ” (рис. 4).

    Дистрибутивы для установки:

    Коментарии

    Комментарии – это то, что пишется после символа # , и представляет интерес лишь как заметка для читающего программу.
    Например:
    print(‘Привет, Мир!) # print – это функция
    или:
    # print – это функция
    print(‘Привет, Мир!) ===== Числа ===== Числа в Python бывают трёх типов: целые, с плавающей точкой и комплексные. * Примером целого числа может служить 2 . * Примерами чисел с плавающей точкой (или «плавающих» для краткости) могут быть 3.23 и 52.3E-4 . Обозначение E показывает степени числа 10. В данном случае 52.3E-4 означает 52.3 • 10 −4 . * Примеры комплексных чисел: (-5+4j) и (2.3 — 4.6j)

    Строки

    Строка – это последовательность символов. Чаще всего строки – это просто некоторые наборы слов. Слова могут быть как на английском языке, так и на любом другом, поддерживаемом стандартом Unicode, что означает почти на любом языке мира. Иногда бывает нужно составить строку на основе каких-либо данных. Вот здесь-то и пригождается метод format().
    Сохраните следующие строки в файл str_format.py :
    age = 26
    name = ‘Swaroop’
    print(‘Возраст <0>– <1>лет.’.format(name, age))
    print(‘Почему <0>забавляется с этим Python?’.format(name))
    Вывод:
    $ python str_format.py
    Возраст Swaroop – 26 лет.
    Почему Swaroop забавляется с этим Python?
    Как это работает:
    В строку могут быть включены определённые обозначения, а впоследствии может быть вызван метод format для замещения этих обозначений соответ- ствующими аргументами. Взгляните на первый случай применения обозначений, где мы пишем <0>, и это соответствует переменной name , являющейся первым аргументом метода format . Аналогично, второе обозначение <1>соответствует переменной age, являющейся вторым аргументом метода format . Заметьте, что Python начинает отсчёт с 0, поэтому первая позиция – номер 0, вторая – номер 1 и т. д. Заметьте, мы ведь могли добиться того же самого результата и объединением строк: ‘Возраст’ + name + ‘ – ‘ + str(age) + ‘ лет.’ , однако вы сами видите, как это некрасиво, и как легко в таком случае допустить ошибку. Во вторых, преобразование в строку делается методом format автоматически, в отличие от явного преобразования в нашем примере. В-третьих, используя метод format , мы можем изменить сообщение, не затрагивая используемых переменных, и наоборот. На всякий случай имейте в виду, что цифры здесь не обязательны. Можно было бы просто написать:
    age = 26
    name = ‘Swaroop’
    print(‘Возраст <> – <> лет.’.format(name, age))
    print(‘Почему <> забавляется с этим Python?’.format(name))
    и получить такой же результат, как и ранее (2).

    Переменные

    Слово «переменные» говорит само за себя – их значение может меняться, а значит, вы можете хранить в переменной всё, что угодно. Переменные – это просто области памяти компьютера, в которых вы храните некоторую информацию. В отличие от констант, к такой информации нужно каким-то образом получать доступ, поэтому переменным даются имена.
    Переменную в Python создать очень просто — нужно присвоить некоторому идентификатору значение при помощи оператора присваивания «=».
    ПРИМЕР:
    a=10
    b=3.1415926
    c=«Hello»
    d=[1, 2, 3]
    В этом примере используются четыре переменные:

    Типы данных

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

    Пример: Использование переменных и констант

    # Имя файла : var.py
    i = 5
    print(i)
    i = i + 1
    print(i)
    s = ‘Это многострочная строка.
    Это вторая её строчка. ‘
    print(s)
    Вывод:
    $ python var.py
    5
    6
    Это многострочная строка.
    Это вторая её строчка.
    Как это работает:
    Вот как эта программа работает. Сперва мы присваиваем значение константы 5 переменной i, используя оператор присваивания ( = ). Эта строка называется предложением и указывает, что должно быть произведено некоторое действие, и в данном случае мы связываем имя переменной i со значением 5. Затем мы печатаем значение i, используя функцию print, которая просто печатает значение переменной на экране. Далее мы добавляем 1 к значению, хранящемуся в i и сохраняем его там. После этого мы печатаем его и получаем значение 6, что неудивительно. Аналогичным образом мы присваиваем строковую константу переменной s, после чего печатаем её.

    Операторы

    Обратите внимание, вычислить значения выражений, данных в примерах, можно также используя интерпретатор интерактивно. Например, для проверки выражения 2 + 3 воспользуйтесь интерактивной командной строкой интерпретатора Python:
    »> 2 + 3
    5
    »> 3 * 5
    15

    Выражения

    Пример (сохраните как expression.py ):
    length = 5
    breadth = 2
    area = length * breadth
    print(‘Площадь равна’, area)
    print(‘Периметр равен’, 2 * (length + breadth))
    Вывод:
    $ python expression.py
    Площадь равна 10
    Периметр равен 14
    Как это работает:
    Длина и ширина прямоугольника хранятся в переменных length и breadth соответственно. Мы используем их для вычисления периметра и площади прямоугольника при помощи выражений. Результат выражения length * breadth сохраняется в переменной area , после чего выводится на экран функцией print. Во втором случае мы напрямую подставляем значение выражения 2 * (length + breadth) в функцию print. Также обратите внимание, как Python «красиво печатает» результат. Несмотря на то, что мы не указали пробела между ‘Площадь равна’ и переменной area, Python подставляет его за нас, чтобы получить красивый и понятный вывод. Программа же остаётся при этом легкочитаемой (поскольку нам не нужно заботиться о пробелах между строками, которые мы выводим).

    Оператор if

    Оператор if используется для проверки условий: если условие верно, выполняется блок выражений (называемый «if-блок»), иначе выполняется другой блок выражений (называемый «else-блок»). Блок «else» является необязательным.
    Пример: (сохраните как if.py )
    number = 23
    guess = int(input(‘Введите целое число : ‘))
    if guess == number:
    print(‘Поздравляю, вы угадали,’) # Здесь начинается новый блок
    print(‘(хотя и не выиграли никакого приза!)’) # Здесь заканчивается новый блок
    elif guess
    Как это работает:
    В этой программе мы принимаем варианты от пользователя и проверяем, совпадают ли они с заранее заданным числом. Мы устанавливаем переменной number значение любого целого числа, какого хотим. Например, 23. После этого мы принимаем вариант числа от пользователя при помощи функции input() . Функции – это всего-навсего многократно используемые фрагменты программы. Мы узнаем о них больше в следующей главе. Мы передаём встроенной функции input строку, которую она выводит на экран и ожидает ввода от пользователя. Как только мы ввели что-нибудь и нажали клавишу Enter , функция input() возвращает строку, которую мы ввели. Затем мы преобразуем полученную строку в число при помощи int() , и сохраняем это значение в переменную guess . Вообще-то, int – это класс, но на данном этапе вам достаточно знать лишь, что при помощи него можно преобразовать строку в целое число (предполагая, что строка содержит целое число). Далее мы сравниваем число, введённое пользователем, с числом, которое мы выбрали заранее. Если они равны, мы печатаем сообщение об успехе. Обратите внимание, что мы используем соответствующие уровни отступа, чтобы указать Python, какие выражения относятся к какому блоку. Вот почему отступы так важны в Python. Обратите внимание, что в конце оператора if стоит двоеточие – этим мы показываем, что далее следует блок выражений. После этого мы проверяем, верно ли, что пользовательский вариант числа меньше загаданного, и если это так, мы информируем пользователя о том, что ему следует выбирать числа немного больше этого. Здесь мы использовали выражение elif , которое попросту объединяет в себе два связанных if else-if else выражения в одно выражение if-elif-else . Это облегчает чтение программы, а также не требует дополнительных отступов. Выражения elif и else также имеют двоеточие в конце логической строки, за которым следуют соответствующие блоки команд (с соответствующим числом отступов, конечно). Внутри if-блока оператора if может быть другой оператор if и так далее – это называется вложенным оператором if . Помните, что части elif и else не обязательны. Минимальная корректная запись оператора if такова:
    if True: print(‘Да, это верно.’)
    После того, как Python заканчивает выполнение всего оператора if вместе с его частями elif и else , он переходит к следующему выражению в блоке, содержащем этот оператор if . В нашем случае это основной блок программы (в котором начинается выполнение программы), а следующее выражение – это print(‘Завершено’) . После этого Python доходит до конца программы и просто выходит из неё. (3)

    Оператор while

    Оператор while позволяет многократно выполнять блок команд до тех пор, пока выполняется некоторое условие. Это один из так называемых операторов цикла. Он также может иметь необязательный пункт else .
    Пример: (сохраните как while.py )
    number = 23
    running = True
    while running:
    guess = int(input(‘Введите целое число : ‘))
    if guess == number:
    print(‘Поздравляю, вы угадали.’)
    running = False # это останавливает цикл while
    elif guess
    Как это работает:
    В этой программе мы продолжаем играть в игру с угадыванием, но преимущество состоит в том, что теперь пользователь может угадывать до тех пор, пока не угадает правильное число, и ему не придётся запускать программу заново для каждой попытки, как это происходило до сих пор. Это наглядно демонстрирует применение оператора while. Мы переместили операторы input и if внутрь цикла while и установили переменную running в значение True перед запуском цикла. Прежде всего проверяется, равно ли значение переменной running True, а затем происходит переход к соответствующему while-блоку. После выполнения этого блока команд условие, которым в данном случае является переменная running , проверяется снова. Если оно истинно, while-блок запускается снова, в противном случае происходит переход к дополнительному else-блоку, а затем – к следующему оператору. Блок else выполняется тогда, когда условие цикла while становится ложным ( False ) – это может случиться даже при самой первой проверке условия. Если у цикла while имеется дополнительный блок else , он всегда выполняется, если только цикл не будет прерван оператором break . True и False называются булевым типом данных, и вы можете считать их эквивалентными значениям 1 и 0 соответственно.

    Цикл for

    Оператор for..in также является оператором цикла, который осуществляет итерацию по последовательности объектов, т.е. проходит через каждый элемент в последовательности.
    Пример: (сохраните как for.py )
    for i in range(1, 5):
    print(i)
    else:
    print(‘Цикл for закончен’)
    Вывод:
    $ python for.py
    1
    2
    3
    4
    Цикл for закончен
    Как это работает:
    В этой программе мы выводим на экран последовательность чисел. Мы генерируем эту последовательность, используя встроенную функцию range 5. Мы задаём два числа, и range возвращает последовательность чисел от первого числа до второго. Например, range(1,5) даёт последовательность [1, 2, 3, 4] . По умолчанию range принимает значение шага, равное 1. Если мы зададим также и третье число range , оно будет служить шагом. Например, range(1,5,2) даст [1,3] . Помните, интервал простирается только до второго числа, т.е. не включает его в себя. Обратите внимание, что range() генерирует последовательность чисел, но только по одному числу за раз – когда оператор for запрашивает следующий элемент. Чтобы увидеть всю последовательность чисел сразу, используйте list(range()). Затем цикл for осуществляет итерацию по этому диапазону — for i in range(1,5) эквивалентно for i in [1, 2, 3, 4], что напоминает присваивание переменной i по одному числу (или объекту) за раз, выполняя блок команд для каждого значения i. В данном случае в блоке команд мы просто выводим значение на экран. Помните, что блок else не обязателен. Если он присутствует, он всегда выполняется один раз после окончания цикла for, если только не указан оператор break. Помните также, что цикл for..in работает для любой последовательности. В нашем случае это список чисел, сгенерированный встроенной функцией range, но в общем случае можно использовать любую последовательность любых объектов!

    Оператор break

    Оператор break служит для прерывания цикла, т.е. остановки выполнения команд даже если условие выполнения цикла ещё не приняло значения False или последовательность элементов не закончилась.
    Важно отметить, что если циклы for или while прервать оператором break, соответствующие им блоки else выполняться не будут.
    Пример: (сохраните как break.py )
    while True:
    s = input(‘Введите что-нибудь : ‘)
    if s == ‘выход’:
    break
    print(‘Длина строки: ‘, len(s))
    print(‘Завершение’)
    Вывод:
    $ python break.py
    Введите что-нибудь : Программировать весело.
    Длина строки: 23
    Введите что-нибудь : Если работа скучна,
    Длина строки: 19
    Введите что-нибудь : Чтобы придать ей весёлый тон —
    Длина строки: 30
    Введите что-нибудь : используй Python!
    Длина строки: 23
    Введите что-нибудь : выход
    Завершение
    Как это работает:
    В этой программе мы многократно считываем пользовательский ввод и выводим на экран длину каждой введённой строки. Для остановки программы мы вводим специальное условие, проверяющее, совпадает ли пользовательский ввод со строкой ‘выход’ . Мы останавливаем программу прерыванием цикла оператором break и достигаем её конца. Длина введённой строки может быть найдена при помощи встроенной функции len .Помните также, что оператор break может применяться и в цикле for (4).

    Оператор continue

    Оператор continue используется для указания Python, что необходимо пропустить все оставшиеся команды в текущем блоке цикла и продолжить со следующей итерации цикла.
    Пример: (сохраните как continue.py )
    while True:
    s = input(‘Введите что-нибудь : ‘)
    if s == ‘выход’:
    break
    if len(s)
    Как это работает:
    В этой программе мы запрашиваем ввод со стороны пользователя, но обрабатываем введённую строку только если она имеет длину хотя бы в 3 символа. Итак, мы используем встроенную функцию len для получения длины строки, и если длина менее 3, мы пропускаем остальные действия в блоке при помощи оператора continue . В противном случае все остальные команды в цикле выполняются, производя любые манипуляции, которые нам нужны. Заметьте, что оператор continue также работает и с циклом for .

    Функции

    Определим простейшую функцию:
    def add(x, y):
    return x + y
    Инструкция return говорит, что нужно вернуть значение. В нашем случае функция возвращает сумму x и y.
    Теперь мы ее можем вызвать:
    »> add(1, 10)
    11
    »> add(‘abc’, ‘def’)
    ‘abcdef ‘
    Функция может быть любой сложности и возвращать любые объекты (списки, кортежи, и даже функции!):
    »> def newfunc(n):
    … def myfunc(x):
    … return x + n
    … return myfunc

    »> new = newfunc(100) # new — это функция
    »> new(200)
    300
    Функция может и не заканчиваться инструкцией return, при этом функция вернет значение None:
    »> def func():
    … pass

    »> print(func())
    None

    Аргументы функции

    Функция может принимать произвольное количество аргументов или не принимать их вовсе. Также распространены функции с произвольным числом аргументов, функции с позиционными и именованными аргументами, обязательными и необязательными.
    »> def func(a, b, c=2): # c — необязательный аргумент
    … return a + b + c

    »> func(1, 2) # a = 1, b = 2, c = 2 (по умолчанию)
    5
    »> func(1, 2, 3) # a = 1, b = 2, c = 3
    6
    »> func(a=1, b=3) # a = 1, b = 3, c = 2
    6
    »> func(a=3, c=6) # a = 3, c = 6, b не определен
    Traceback (most recent call last):
    File «», line 1, in
    func(a=3, c=6)
    TypeError: func() takes at least 2 arguments (2 given)
    Функция также может принимать переменное количество позиционных аргументов, тогда перед именем ставится *:
    »> def func(*args):
    … return args

    »> func(1, 2, 3, ‘abc’)
    (1, 2, 3, ‘abc’)
    »> func()
    ()
    »> func(1)
    (1,)
    Как видно из примера, args — это кортеж из всех переданных аргументов функции, и с переменной можно работать также, как и с кортежем.
    Функция может принимать и произвольное число именованных аргументов, тогда перед именем ставится :
    »> def func(
    kwargs):
    … return kwargs

    »> func(a=1, b=2, c=3)
    <'a': 1, 'c': 3, 'b': 2>
    »> func()
    <>
    »> func(a=’python’)
    <'a': 'python'>
    В переменной kwargs у нас хранится словарь.

    Анонимные функции

    Анонимные функции могут содержать лишь одно выражение, но и выполняются они быстрее. Анонимные функции создаются с помощью инструкции lambda. Кроме этого, их не обязательно присваивать переменной, как делали мы инструкцией def func():
    »> func = lambda x, y: x + y
    »> func(1, 2)
    3
    »> func(‘a’, ‘b’)
    ‘ab’
    »> (lambda x, y: x + y)(1, 2)
    3
    »> (lambda x, y: x + y)(‘a’, ‘b’)
    ‘ab’
    lambda функции, в отличие от обычной, не требуется инструкция return, а в остальном, ведет себя точно так же:
    »> func = lambda *args: args
    »> func(1, 2, 3, 4)
    (1, 2, 3, 4)

    Модули


    Модулем в Python называется любой файл с программой.Подключить модуль можно с помощью инструкции import. После ключевого слова import указывается название модуля. Одной инструкцией можно подключить несколько модулей, хотя этого не рекомендуется делать, так как это снижает читаемость кода (5). Импортируем модули time и random.
    »> import time, random
    »> time.time()
    1376047104.056417
    »> random.random()
    0.9874550833306869 Текст кода
    Если название модуля слишком длинное, или оно вам не нравится по каким-то другим причинам, то для него можно создать псевдоним, с помощью ключевого слова as.
    »> import math as m
    »> m.e
    2.718281828459045
    Подключить определенные атрибуты модуля можно с помощью инструкции from. Она имеет несколько форматов:
    from import [ as ], [ [ as ] …]
    from import *
    Первый формат позволяет подключить из модуля только указанные вами атрибуты. Для длинных имен также можно назначить псевдоним, указав его после ключевого слова as.
    »> from math import e, ceil as c
    »> e
    2.718281828459045
    »> c(4.6)
    5
    Второй формат инструкции from позволяет подключить все (точнее, почти все) переменные из модуля.

    Создание своего модуля на Python

    Создадим файл mymodule.py, в которой определим какие-нибудь функции:
    def hello():
    print(‘Hello, world!’)
    def fib(n):
    a = b = 1
    for i in range(n — 2):
    a, b = b, a + b
    return b
    Теперь в этой же папке создадим другой файл, например, main.py:
    import mymodule
    mymodule.hello()
    print(mymodule.fib(10))
    Выведет:
    Hello, world!
    55

    Структуры данных

    Структуры данных позволяют хранить и обрабатывать множество однотипных данных, а так же имеющие встроенные методы для добавления, поиска, изменения и удаления данных. Так как в Python используется динамическая типизация, так что типы данных определяются автоматически во время исполнения, и заранее объявлять их не нужно.
    Изменяемые:

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

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

    Изменить. Я был привлечен к задаче в комментариях (частично, по-видимому, фанатиками FP на Python, но не исключительно), чтобы не давать больше объяснений/примеров, поэтому, расширение ответа на поставку некоторых.

    lambda , тем более map (и filter ), и, в особенности reduce , вряд ли будут правильным инструментом для работы на Python, что сильно язык мультипарадигмы.

    lambda основное преимущество (?) по сравнению с обычным выражением def заключается в том, что он выполняет функцию анонимного, а def дает функции имя — и для этого очень сомнительный преимущество в том, что вы платите огромную цену (тело функции ограничено одним выражением, результирующий объект функции не разборчив, сам недостаток имени иногда затрудняет понимание трассировки стека или отлаживает проблему — мне нужно идти на -!).

    Считайте, что, вероятно, самая идиотичная идиома, которую вы иногда видите в «Python» (Python с «кавычками», потому что это явно не идиоматический Python — это плохая транслитерация из идиоматической схемы или аналогично тому, как более частое злоупотребление ООП в Python — плохая транслитерация с Java и т.п.):

    назначив лямбда имени, этот подход сразу же выбрасывает вышеупомянутое «преимущество» и не теряет никаких недостатков! Например, inc не знает его имя — inc.__name__ — бесполезная строка ‘ ‘ — удача в понимании трассировки стека несколькими из них;-). Разумеется, правильный способ Python для достижения желаемой семантики в этом простом случае:

    Теперь inc.__name__ — это строка ‘inc’ , как это должно быть ясно, и объект является макробливым — семантика в остальном идентична (в этом простом случае, когда желаемая функциональность удобно помещается в простом выражении — def также делает его тривиально простым для рефакторинга, если вам нужно временно или постоянно вставлять такие выражения, как print или raise , конечно).

    lambda является (частью) выражения, в то время как def является (частью) инструкции — что один бит синтаксического сахара, который заставляет людей использовать lambda иногда. Многие энтузиасты FP (как и многие ООП и процедурные фанаты) не любят Python достаточно сильное различие между выражениями и высказываниями (часть общей позиции по отношению к Command-Query Separation). Я думаю, что, когда вы используете язык, вам лучше использовать его «с зерном» — способ использования , а не бороться с ним; поэтому я программирую Python в Pythonic, Scheme in the Schematic (;-) way, Fortran в стиле Fortesque (?) и т.д.: -).

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

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

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

    . мы можем получить почти обратно к легко полученной производительности простейшего и наиболее очевидного, компактного и читаемого подхода (простой, элементарный, тривиальный цикл). Это указывает на еще одну проблему с lambda , на самом деле: производительность! Для достаточно простых операций, таких как умножение, накладные расходы на вызов функции довольно значительны по сравнению с фактической выполняемой операцией — reduce (и map и filter ) часто заставляет вас вставлять такой вызов функции, где простые циклы, представления списков и выражения генератора, позволяют читаемость, компактность и скорость оперативных операций.

    Возможно, даже хуже, чем вышеописанное «назначить лямбда для имени», анти-идиома на самом деле является следующим анти-идиомом, например. для сортировки списка строк по их длине:

    вместо очевидного, читаемого, компактного, более быстрого

    Здесь использование lambda ничего не делает, кроме вставки уровня косвенности — без какого-либо хорошего эффекта и большого числа плохих.

    Мотивация использования lambda часто позволяет использовать map и filter вместо более предпочтительного понимания цикла или списка, которое позволит вам делать простые, нормальные вычисления в строке; вы все равно платите этот «уровень косвенности», конечно. Это не Pythonic, чтобы задаться вопросом: «Должен ли я использовать список или карту здесь»: просто всегда используйте listcomps, когда они кажутся применимыми, и вы не знаете, какой из них выбрать, на основе «должен быть один и предпочтительно только один, очевидный способ сделать что-то». Вы часто пишете listcomps, которые не могут быть разумно переведены на карту (вложенные циклы, предложения if и т.д.), В то время как нет вызова map , который не может быть правильно переписан как listcomp.

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

    itertools , как отметил комментатор, включает imap и ifilter : разница в том, что, как и все itertools, они основаны на потоках (например, map и filter встроенные в Python 3, но отличается от тех, что были встроены в Python 2). itertools предлагает набор строительных блоков, которые хорошо сочетаются друг с другом и великолепная производительность: особенно если вы обнаружите, что имеете возможность работать с очень длинными (или даже неограниченными!) последовательностями, вы обязаны сделать это для себя, чтобы ознакомиться с itertools — — их целая глава в документах делает для хорошего чтения, а recipes, в частности, весьма поучительны.

    Написание собственных функций более высокого порядка часто полезно, особенно когда они подходят для использования в качестве декораторов (оба декоратора функций, как объяснено в этой части документов и декораторов классов, введенных в Python 2.6). Не забывайте использовать functools.wraps на ваших декораторах функций (чтобы сохранить метаданные обернутой функции)!

    Итак, суммируя. все, что вы можете кодировать с помощью lambda , map и filter , вы можете кодировать (чаще, чем не выгодно) с помощью def (named functions) и listcomps — и, как правило, перемещение на одну ступень до генераторов, генераторных выражений или itertools , еще лучше. reduce соответствует юридическому определению «привлекательной неприятности». вряд ли когда-либо правильный инструмент для работы (почему он не является встроенным в Python 3, наконец-то! -).

    Функциональное программирование на языке Python

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

    Учитывая список строк (L) и строку (S), мне нужно найти L [i] ^ S. Если S существует в L, не сверьте строки. L [i] ^ S означало бы xoring байты в одном и том же положении друг с другом.

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

    Затем я пытаюсь написать код для xor строк вместе.

    Затем, наконец, я пытаюсь выполнить это в списке строк и строки.

    При запуске вышеприведенной строки я получаю сообщение об ошибке:

    Что я делаю неправильно?

    Есть ли что-то не так, как я пытаюсь решить проблему с помощью функционального программирования?

  • Любые очевидные улучшения, о которых вы можете подумать (улучшения должны были бы соответствовать функциональной парадигме тоже — я делаю это как мысленное упражнение, а не в каком-либо проекте).
  • Функциональное программирование на языке Python и C ++ [закрыт]

    December 2020

    1k раз

    Есть ли хорошая книга для функционального программирования на Python или C ++? Мне нужно, чтобы освоить функциональное программирование на этих языках.

    7 ответы

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

    В Python вы можете использовать функции для редактирования dictionarys ведьмы довольно функционально. Используйте лямбда с функций высшего порядка. Вы должны избегать классов и наследования.

    Я не могу действительно сказать много о C ++. Может быть, вы можете найти некоторые функциональные datastructures, а затем писать функции на них. Посмотрите на библиотеку, которая предоставляет такие функции, как карты, уменьшить .

    C ++ 0x должны поддерживать закрытия и каррирование (больше или меньше), так, что будет лучше.

    • Старайтесь писать immutible слои на Librarys (быть awair, что это привычка performe хорошо)
    • Посмотрите на Librarys, которые написаны в функциональном стиле

    Изменить: Я бы рекомендовал схему обучения его действительно мало, и вы можете забрать его быстро. Почитайте что-нибудь вроде SICP или Литтл Schemer, которые научат вас recursiv мышления.

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

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

    Только будущая версия C ++ поддерживает лямбды / анонимные функции. Я предполагаю, что Boost.Lambda поддерживает C ++ функционального программирования, но это на самом деле не первый класс гражданин C ++ еще.

    Книги о функциональном программировании обычно используют функциональные языки. Как Haskell, Miranda, Lisp, Scheme, OCaml, Javascript и так далее.

    EDIT: Я утаивать свое мнение на Python сейчас. Оказывается, я ошибался несколько вещей.

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

    Хотя это не книга, вот сайт , который может , по крайней мере , чтобы вы начали на некоторые вещи. http://www.ibm.com/developerworks/library/l-prog.html

    Насколько на самом деле понимания функционального программирования, я хотел бы предложить что-то вроде «The Little Schemer», чтобы получить быструю ручку на схеме. Затем вы можете применить идеи питона.

    Для Perl, я могу порекомендовать « высший порядок Perl ».

    Не знаю, Python или C ++, хотя.

    В поисках информации о функциональном программировании на Python, я нашел этот веб-страницу, чтобы быть очень полезными:

    Ссылки часть содержит много сырой информации.

    Если вы ищете книгу, охватывающую только функциональное программирование в Python, я не знаю об этом.

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

    Функциональное программирование на Python

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

    Содержание

    Возможности

    Определение и использование функции


    Функция в Python может быть определена с помощью оператора def или лямбда-выражением. Следующие операторы эквивалентны:

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

    При вызове функции задаются фактические аргументы. Например:

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

    Функция всегда возвращает только одно значение (или None , если значение не задано в операторе return или этот оператор не встречен по достижении конца определения функции). Однако, это незначительное ограничение, так как возвращаемым значением может быть кортеж.

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

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

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

    Списковые включения

    Списковое включение [1] (англ. list comprehension ) — наиболее выразительное из функциональных средств Python. Например, для вычисления списка квадратов положительных целых чисел, меньших 10, можно использовать выражение:

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

    В Python есть функции, одним из аргументом которых являются другие функции: map() , filter() , reduce() , apply() .

    Функция map() позволяет обрабатывать одну или несколько последовательностей с помощью заданной функции:

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

    filter()

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

    То же самое с помощью списковых выражений:

    reduce()

    Для организации цепочечных вычислений в списке можно использовать функцию reduce() . Например, произведение элементов списка может быть вычислено так (Python 2):

    Вычисления происходят в следующем порядке:

    Цепочка вызовов связывается с помощью промежуточного результата ( res ). Если список пустой, просто используется третий параметр (в случае произведения нуля множителей это 1):

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

    Для наиболее распространенных операций в Python есть встроенные функции:

    В Python 3 встроенной функции reduce() нет, но её можно найти в модуле functools .

    apply()

    Функция для применения другой функции к позиционным и именованным аргументам, заданным списком и словарем соответственно (Python 2):

    В Python 3 вместо функции apply() следует использовать специальный синтаксис:

    Замыкания

    Функции, определяемые внутри других функций, представляют собой полноценные замыкания (англ. closures ) [2] :

    Итераторы

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

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

    Следующий пример иллюстрирует использование модуля itertools :

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

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

    Модуль functools

    В Python 2.5 появился модуль functools и в частности возможность частичного применения функций:

    (Частичное применение функций также можно реализовать с помощью замыканий или функторов)

    Ленивые вычисления

    Ленивые вычисления можно организовать в Python несколькими способами, используя различные механизмы:

    • простейшие логические операции or и and не вычисляют второй операнд, если результат определяется первым операндом
    • лямбда-выражения
    • определенные пользователем классы с ленивой логикой вычислений [3] или функторы
    • Генераторы и генераторные выражения
    • (Python 2.5) if-выражение имеет «ленивую» семантику (вычисляется только тот операнд, который нужен)

    Пример, который иллюстрирует работу if-выражения. С помощью оператора print можно проследить, какие функции реально вызывались:

    Некоторые примеры из книги рецептов:

    • Ленивая сортировка [4]
    • Ленивый обход графа [5]
    • Ленивое вычисление свойств [6]
    • Карринг [7]

    Функторы

    Функторами называют объекты, синтаксически подобные функциям, то есть поддерживающие операцию вызова. Для определения функтора нужно перегрузить оператор () с помощью метода __call__ . В Python функторы полностью аналогичны функциям, за исключением специальных атрибутов ( func_code и некоторых других). Например, функторы можно передавать в качестве функций обратного вызова (callback) в С-код. Функторы позволяют заменить некоторые приёмы, связанные с использованием замыкания, статических переменных и т. п.

    Ниже представлено замыкание и эквивалентный ему функтор:

    Следует отметить, что код, использующий замыкание, будет исполняться быстрее, чем код с функтором. Это связанно с необходимостью получения атрибута val у переменной self (то есть функтор проделывает на одну Python операцию больше). Также функторы нельзя использовать для создания декораторов с параметрами. С другой стороны, функторам доступны все возможности ООП в Python, что делает их очень полезными для функционального программирования. Например, можно написать функтор, который будет «запоминать» исполняемые над ним операции и затем повторять их. Для этого достаточно соответствующим образом перегрузить специальные методы.

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

    Определенный подобным образом функтор создает значительные накладные расходы, так как при каждом вызове проходит по вызовам всех вложенных lambda . Можно оптимизировать функтор, применив технику генерирования байткода во время исполнения. Соответствующий пример и тесты на скорость есть в Примерах Python программ. При использовании этой техники скорость исполнения не будет отличаться от «статического» кода (если не считать времени, требующегося на однократное конструирование результирующей функции). Вместо байтокода Python можно генерировать на выходе, например, код на языке программирования C, других языках программирования или XML-файлы.

    Несмотря на накладные расходы, ленивое вычисление может дать заметный выигрыш в скорости в случаях, когда действия, оборачиваемые ленивым функтором, достаточно дороги — например, включают объёмные вычисления или доступ к диску. Предположим некоторый промежуточный результат X лениво вычисляется перед условным оператором; для него будет создана цепочка функторов. В той ветке условного оператора, где значение X не требуется по ходу вычисления, эта цепочка функторов будет просто отброшена, не приведя к дорогостоящему вычислению. В другой ветке, где X требуется для вычисления конечного результата функции, цепочка функторов произведёт его вычисление. При этом программисту не нужно отслеживать, в какой из веток алгоритма значение может не потребоваться: он может рассчитывать, что дорогостоящее вычисление X произойдёт только тогда, когда его результат не будет отброшен.

    Напишите отзыв о статье «Функциональное программирование на Python»

    Примечания

    1. Прохоренок, 2011, с. 123-124.
    2. [www.diveinto.org/python3/generators.html Dive into Python 3, Ch. 6. Closures and Generators]
    3. [freshmeat.net/projects/lazypy/ Пакет lazypy]
    4. [code.activestate.com/recipes/280501/ Lazy sorting]
    5. [code.activestate.com/recipes/498247/ Lazy Traversal of Directed Graphs]
    6. [code.activestate.com/recipes/363602-lazy-property-evaluation/ Lazy property evaluation]
    7. [code.activestate.com/recipes/52549/ curry — associating parameters with a function]

    Ссылки

    • [linuxgazette.net/109/pramode.html Functional Programming with Python], Pramode C.E., Linux Gazette, 2004
    • [www-128.ibm.com/developerworks/library/l-prog.html Charming Python: Functional programming in Python], Dav >Литература
    • Прохоренок Н. А. Python. Самое необходимое. — БХВ-Петербург, 2011. — 416 с. — ISBN 978-5-9775-0614-4.
    • David M. Beazley. Python Essential Reference, 4th Edition. — Addison-Wesley Professional, 2010. — 744 с. — ISBN 978-0-672-32978-4. Часть главы 6 на LinuxJournal: [www.linuxjournal.com/content/book-excerpt-chapter-6-functions-and-functional-programming Functions and functional programming] (англ.)
    • Mark Pilgrim. Dive Into Python. — Apress, 2004. — 413 с. — ISBN 9781590593561. . [www.diveintopython.net/functional_programming/ Глава о функциональном программировании] (англ.)
    • David Mertz. Functional Programming in Python. — O’Reilly, 2015. — ISBN 978-1-491-92856-1. (англ.)
    • Steven Lott. Functional Python Programming. — Packt Publishing Ltd, 2015. — 360 p. — ISBN 978-1-78439-761-6. (англ.)

    : неверное или отсутствующее изображение

    Для улучшения этой статьи желательно ? :

    • Проставив сноски, внести более точные указания на источники.
    • Викифицировать статью.
    • Найти и оформить в виде сносок ссылки на независимые авторитетные источники, подтверждающие написанное.К:Википедия:Статьи без источников (тип: не указан)

    Отрывок, характеризующий Функциональное программирование на Python

    Предчувствие Анны Павловны действительно оправдалось. На другой день, во время молебствия во дворце по случаю дня рождения государя, князь Волконский был вызван из церкви и получил конверт от князя Кутузова. Это было донесение Кутузова, писанное в день сражения из Татариновой. Кутузов писал, что русские не отступили ни на шаг, что французы потеряли гораздо более нашего, что он доносит второпях с поля сражения, не успев еще собрать последних сведений. Стало быть, это была победа. И тотчас же, не выходя из храма, была воздана творцу благодарность за его помощь и за победу.
    Предчувствие Анны Павловны оправдалось, и в городе все утро царствовало радостно праздничное настроение духа. Все признавали победу совершенною, и некоторые уже говорили о пленении самого Наполеона, о низложении его и избрании новой главы для Франции.
    Вдали от дела и среди условий придворной жизни весьма трудно, чтобы события отражались во всей их полноте и силе. Невольно события общие группируются около одного какого нибудь частного случая. Так теперь главная радость придворных заключалась столько же в том, что мы победили, сколько и в том, что известие об этой победе пришлось именно в день рождения государя. Это было как удавшийся сюрприз. В известии Кутузова сказано было тоже о потерях русских, и в числе их названы Тучков, Багратион, Кутайсов. Тоже и печальная сторона события невольно в здешнем, петербургском мире сгруппировалась около одного события – смерти Кутайсова. Его все знали, государь любил его, он был молод и интересен. В этот день все встречались с словами:
    – Как удивительно случилось. В самый молебен. А какая потеря Кутайсов! Ах, как жаль!
    – Что я вам говорил про Кутузова? – говорил теперь князь Василий с гордостью пророка. – Я говорил всегда, что он один способен победить Наполеона.
    Но на другой день не получалось известия из армии, и общий голос стал тревожен. Придворные страдали за страдания неизвестности, в которой находился государь.
    – Каково положение государя! – говорили придворные и уже не превозносили, как третьего дня, а теперь осуждали Кутузова, бывшего причиной беспокойства государя. Князь Василий в этот день уже не хвастался более своим protege Кутузовым, а хранил молчание, когда речь заходила о главнокомандующем. Кроме того, к вечеру этого дня как будто все соединилось для того, чтобы повергнуть в тревогу и беспокойство петербургских жителей: присоединилась еще одна страшная новость. Графиня Елена Безухова скоропостижно умерла от этой страшной болезни, которую так приятно было выговаривать. Официально в больших обществах все говорили, что графиня Безухова умерла от страшного припадка angine pectorale [грудной ангины], но в интимных кружках рассказывали подробности о том, как le medecin intime de la Reine d’Espagne [лейб медик королевы испанской] предписал Элен небольшие дозы какого то лекарства для произведения известного действия; но как Элен, мучимая тем, что старый граф подозревал ее, и тем, что муж, которому она писала (этот несчастный развратный Пьер), не отвечал ей, вдруг приняла огромную дозу выписанного ей лекарства и умерла в мучениях, прежде чем могли подать помощь. Рассказывали, что князь Василий и старый граф взялись было за итальянца; но итальянец показал такие записки от несчастной покойницы, что его тотчас же отпустили.
    Общий разговор сосредоточился около трех печальных событий: неизвестности государя, погибели Кутайсова и смерти Элен.
    На третий день после донесения Кутузова в Петербург приехал помещик из Москвы, и по всему городу распространилось известие о сдаче Москвы французам. Это было ужасно! Каково было положение государя! Кутузов был изменник, и князь Василий во время visites de condoleance [визитов соболезнования] по случаю смерти его дочери, которые ему делали, говорил о прежде восхваляемом им Кутузове (ему простительно было в печали забыть то, что он говорил прежде), он говорил, что нельзя было ожидать ничего другого от слепого и развратного старика.
    – Я удивляюсь только, как можно было поручить такому человеку судьбу России.
    Пока известие это было еще неофициально, в нем можно было еще сомневаться, но на другой день пришло от графа Растопчина следующее донесение:
    «Адъютант князя Кутузова привез мне письмо, в коем он требует от меня полицейских офицеров для сопровождения армии на Рязанскую дорогу. Он говорит, что с сожалением оставляет Москву. Государь! поступок Кутузова решает жребий столицы и Вашей империи. Россия содрогнется, узнав об уступлении города, где сосредоточивается величие России, где прах Ваших предков. Я последую за армией. Я все вывез, мне остается плакать об участи моего отечества».
    Получив это донесение, государь послал с князем Волконским следующий рескрипт Кутузову:
    «Князь Михаил Иларионович! С 29 августа не имею я никаких донесений от вас. Между тем от 1 го сентября получил я через Ярославль, от московского главнокомандующего, печальное известие, что вы решились с армиею оставить Москву. Вы сами можете вообразить действие, какое произвело на меня это известие, а молчание ваше усугубляет мое удивление. Я отправляю с сим генерал адъютанта князя Волконского, дабы узнать от вас о положении армии и о побудивших вас причинах к столь печальной решимости».

    Девять дней после оставления Москвы в Петербург приехал посланный от Кутузова с официальным известием об оставлении Москвы. Посланный этот был француз Мишо, не знавший по русски, но quoique etranger, Busse de c?ur et d’ame, [впрочем, хотя иностранец, но русский в глубине души,] как он сам говорил про себя.
    Государь тотчас же принял посланного в своем кабинете, во дворце Каменного острова. Мишо, который никогда не видал Москвы до кампании и который не знал по русски, чувствовал себя все таки растроганным, когда он явился перед notre tres gracieux souverain [нашим всемилостивейшим повелителем] (как он писал) с известием о пожаре Москвы, dont les flammes eclairaient sa route [пламя которой освещало его путь].
    Хотя источник chagrin [горя] г на Мишо и должен был быть другой, чем тот, из которого вытекало горе русских людей, Мишо имел такое печальное лицо, когда он был введен в кабинет государя, что государь тотчас же спросил у него:
    – M’apportez vous de tristes nouvelles, colonel? [Какие известия привезли вы мне? Дурные, полковник?]
    – Bien tristes, sire, – отвечал Мишо, со вздохом опуская глаза, – l’abandon de Moscou. [Очень дурные, ваше величество, оставление Москвы.]
    – Aurait on livre mon ancienne capitale sans se battre? [Неужели предали мою древнюю столицу без битвы?] – вдруг вспыхнув, быстро проговорил государь.
    Мишо почтительно передал то, что ему приказано было передать от Кутузова, – именно то, что под Москвою драться не было возможности и что, так как оставался один выбор – потерять армию и Москву или одну Москву, то фельдмаршал должен был выбрать последнее.
    Государь выслушал молча, не глядя на Мишо.
    – L’ennemi est il en ville? [Неприятель вошел в город?] – спросил он.
    – Oui, sire, et elle est en cendres a l’heure qu’il est. Je l’ai laissee toute en flammes, [Да, ваше величество, и он обращен в пожарище в настоящее время. Я оставил его в пламени.] – решительно сказал Мишо; но, взглянув на государя, Мишо ужаснулся тому, что он сделал. Государь тяжело и часто стал дышать, нижняя губа его задрожала, и прекрасные голубые глаза мгновенно увлажились слезами.
    Но это продолжалось только одну минуту. Государь вдруг нахмурился, как бы осуждая самого себя за свою слабость. И, приподняв голову, твердым голосом обратился к Мишо.
    – Je vois, colonel, par tout ce qui nous arrive, – сказал он, – que la providence exige de grands sacrifices de nous… Je suis pret a me soumettre a toutes ses volontes; mais dites moi, Michaud, comment avez vous laisse l’armee, en voyant ainsi, sans coup ferir abandonner mon ancienne capitale? N’avez vous pas apercu du decouragement. [Я вижу, полковник, по всему, что происходит, что провидение требует от нас больших жертв… Я готов покориться его воле; но скажите мне, Мишо, как оставили вы армию, покидавшую без битвы мою древнюю столицу? Не заметили ли вы в ней упадка духа?]
    Увидав успокоение своего tres gracieux souverain, Мишо тоже успокоился, но на прямой существенный вопрос государя, требовавший и прямого ответа, он не успел еще приготовить ответа.
    – Sire, me permettrez vous de vous parler franchement en loyal militaire? [Государь, позволите ли вы мне говорить откровенно, как подобает настоящему воину?] – сказал он, чтобы выиграть время.
    – Colonel, je l’exige toujours, – сказал государь. – Ne me cachez rien, je veux savoir absolument ce qu’il en est. [Полковник, я всегда этого требую… Не скрывайте ничего, я непременно хочу знать всю истину.]
    – Sire! – сказал Мишо с тонкой, чуть заметной улыбкой на губах, успев приготовить свой ответ в форме легкого и почтительного jeu de mots [игры слов]. – Sire! j’ai laisse toute l’armee depuis les chefs jusqu’au dernier soldat, sans exception, dans une crainte epouvantable, effrayante… [Государь! Я оставил всю армию, начиная с начальников и до последнего солдата, без исключения, в великом, отчаянном страхе…]
    – Comment ca? – строго нахмурившись, перебил государь. – Mes Russes se laisseront ils abattre par le malheur… Jamais. [Как так? Мои русские могут ли пасть духом перед неудачей… Никогда. ]
    Этого только и ждал Мишо для вставления своей игры слов.
    – Sire, – сказал он с почтительной игривостью выражения, – ils craignent seulement que Votre Majeste par bonte de c?ur ne se laisse persuader de faire la paix. Ils brulent de combattre, – говорил уполномоченный русского народа, – et de prouver a Votre Majeste par le sacrifice de leur vie, combien ils lui sont devoues… [Государь, они боятся только того, чтобы ваше величество по доброте души своей не решились заключить мир. Они горят нетерпением снова драться и доказать вашему величеству жертвой своей жизни, насколько они вам преданы…]
    – Ah! – успокоенно и с ласковым блеском глаз сказал государь, ударяя по плечу Мишо. – Vous me tranquillisez, colonel. [А! Вы меня успокоиваете, полковник.]
    Государь, опустив голову, молчал несколько времени.
    – Eh bien, retournez a l’armee, [Ну, так возвращайтесь к армии.] – сказал он, выпрямляясь во весь рост и с ласковым и величественным жестом обращаясь к Мишо, – et dites a nos braves, dites a tous mes bons sujets partout ou vous passerez, que quand je n’aurais plus aucun soldat, je me mettrai moi meme, a la tete de ma chere noblesse, de mes bons paysans et j’userai ainsi jusqu’a la derniere ressource de mon empire. Il m’en offre encore plus que mes ennemis ne pensent, – говорил государь, все более и более воодушевляясь. – Mais si jamais il fut ecrit dans les decrets de la divine providence, – сказал он, подняв свои прекрасные, кроткие и блестящие чувством глаза к небу, – que ma dinastie dut cesser de rogner sur le trone de mes ancetres, alors, apres avoir epuise tous les moyens qui sont en mon pouvoir, je me laisserai croitre la barbe jusqu’ici (государь показал рукой на половину груди), et j’irai manger des pommes de terre avec le dernier de mes paysans plutot, que de signer la honte de ma patrie et de ma chere nation, dont je sais apprecier les sacrifices. [Скажите храбрецам нашим, скажите всем моим подданным, везде, где вы проедете, что, когда у меня не будет больше ни одного солдата, я сам стану во главе моих любезных дворян и добрых мужиков и истощу таким образом последние средства моего государства. Они больше, нежели думают мои враги… Но если бы предназначено было божественным провидением, чтобы династия наша перестала царствовать на престоле моих предков, тогда, истощив все средства, которые в моих руках, я отпущу бороду до сих пор и скорее пойду есть один картофель с последним из моих крестьян, нежели решусь подписать позор моей родины и моего дорогого народа, жертвы которого я умею ценить. ] Сказав эти слова взволнованным голосом, государь вдруг повернулся, как бы желая скрыть от Мишо выступившие ему на глаза слезы, и прошел в глубь своего кабинета. Постояв там несколько мгновений, он большими шагами вернулся к Мишо и сильным жестом сжал его руку пониже локтя. Прекрасное, кроткое лицо государя раскраснелось, и глаза горели блеском решимости и гнева.
    – Colonel Michaud, n’oubliez pas ce que je vous dis ici; peut etre qu’un jour nous nous le rappellerons avec plaisir… Napoleon ou moi, – сказал государь, дотрогиваясь до груди. – Nous ne pouvons plus regner ensemble. J’ai appris a le connaitre, il ne me trompera plus… [Полковник Мишо, не забудьте, что я вам сказал здесь; может быть, мы когда нибудь вспомним об этом с удовольствием… Наполеон или я… Мы больше не можем царствовать вместе. Я узнал его теперь, и он меня больше не обманет…] – И государь, нахмурившись, замолчал. Услышав эти слова, увидав выражение твердой решимости в глазах государя, Мишо – quoique etranger, mais Russe de c?ur et d’ame – почувствовал себя в эту торжественную минуту – entousiasme par tout ce qu’il venait d’entendre [хотя иностранец, но русский в глубине души… восхищенным всем тем, что он услышал] (как он говорил впоследствии), и он в следующих выражениях изобразил как свои чувства, так и чувства русского народа, которого он считал себя уполномоченным.

    Python. Лекция 3. Элементы функционального программирования.

      Ольга Остроградская 2 лет назад Просмотров:

    1 Python. Лекция 3. Элементы функционального программирования. Что такое функциональное программирование? Функции являются абстракциями, в которых детали реализации некоторого действия скрываются за отдельным именем. Хорошо написанный набор функций позволяет использовать их много раз. Стандартная библиотека Python содержит множество готовых и отлаженных функций, многие из которых достаточно универсальны, чтобы работать с широким спектром входных данных. Даже если некоторый участок кода не используется несколько раз, но по входным и выходным данным он достаточно автономен, его смело можно выделить в отдельную функцию. Эта лекция более ориентирована на практические соображения, а не на теорию функционального программирования. Однако там, где нужно, будут употребляться и поясняться соответствующие термины. Далее будут подробно рассмотрены описание и использование функций в Python, рекурсия, передача и возврат функций в качестве параметров, обработка последовательностей и итераторы, а также такое понятие как генератор. Будет продемонстрировано, что в Python функции являются объектами (и, значит, могут быть переданы в качестве параметров и возвращены в результате выполнения функций). Кроме того, речь пойдет о том, как можно реализовать некоторые механизмы функционального программирования, не имеющие в Python прямой синтаксической поддержки, но широко распространенные в языках функционального программирования. Функциональное программирование — это стиль программирования, использующий только композиции функций. Другими словами, это программирование в выражениях, а не в императивных командах. Как отмечает Дэвид Мертц (David Mertz) в своей статье о функциональном программировании на Python, «функциональное программирование — программирование на функциональных языках (LISP, ML, OCAML, Haskell. )», основными атрибутами которых являются: «Наличие функций первого класса (функции наравне с другими объектами можно передавать внутрь функций). Рекурсия является основной управляющей структурой в программе. Обработка списков (последовательностей). Запрещение побочных эффектов у функций, что в первую очередь означает отсутствие присваивания (в «чистых» функциональных языках) Запрещение операторов, основной упор делается на выражения. Вместо операторов вся программа в идеале — одно выражение с сопутствующими определениями. Ключевой вопрос: что нужно вычислить, а не как. Использование функций более высоких порядков (функции над функциями над функциями)».

    2 Функциональная программа В математике функция отображает объекты из одного множества ( множества определения функции ) в другое ( множество значений функции ). Математические функции (их называют чистыми ) «механически», однозначно вычисляют результат по заданным аргументам. Чистые функции не должны хранить в себе какие-либо данные между двумя вызовами. Их можно представлять себе черными ящиками, о которых известно только то, что они делают, но совсем не важно, как. Программы в функциональном стиле конструируются как композиция функций. При этом функции понимаются почти так же, как и в математике: они отображают одни объекты в другие. В программировании «чистые» функции — идеал, не всегда достижимый на практике. Практически полезные функции обычно имеют побочный эффект: сохраняют состояние между вызовами или меняют состояние других объектов. Например, без побочных эффектов невозможно представить себе функции ввода-вывода. Собственно, такие функции ради этих «эффектов» и используются. Кроме того, математические функции легко работают с объектами, требующими бесконечного объема информации (например, вещественные числа). В общем случае компьютерная программа может выполнить лишь приближенные вычисления. Кстати, бинарные операции » + «, » — «, » * «, » / «, которые записываются в выражениях, являются «математическими» функциями над двумя аргументами — операндами. Их используют настолько часто, что синтаксис языка программирования имеет для них более короткую запись. Модуль operator позволяет представлять эти операции в функциональном стиле: >>> from operator import add, mul >>> print add(2, mul(3, 4)) 14 Функция: определение и вызов Как уже говорилось, определить функцию в Python можно двумя способами: с помощью оператора def и lambda -выражения. Первый способ позволяет использовать операторы. При втором — определение функции может быть только выражением. Забегая вперед, можно заметить, что методы классов определяются так же, как и функции. Отличие состоит в специальном смысле первого аргумента self (в нем передается экземпляр класса). Лучше всего рассмотреть синтаксис определения функции на нескольких примерах. После определения соответствующей функции показан один или несколько вариантов ее вызова (некоторые примеры взяты из стандартной библиотеки). Определение функции должно содержать список формальных параметров и тело определения функции. В случае с оператором def функции также задается некоторое имя. Формальные параметры являются локальными именами внутри тела определения функции, а при вызове функции они оказываются связанными с объектами, переданными как фактические параметры. Значения по умолчанию вычисляются в момент выполнения оператора def, и потому в них можно использовать видимые на момент определения имена. Вызов функции синтаксически выглядит как объект-функция(фактические параметры). Обычно объект-функция — это просто имя функции, хотя это может быть и любое выражение, которое в результате вычисления дает исполняемый объект. Функция одного аргумента:

    3 def swapcase(s): return s.swapcase() print swapcase(«abc») Функция двух аргументов, один из которых необязателен и имеет значение по умолчанию: def inc(n, delta=1): return n+delta print inc(12) print inc(12, 2) Функция с одним обязательным аргументом, с одним, имеющим значение по умолчанию и неопределенным числом именованных аргументов: def wrap(text, w digits = [] while n > 0:

    4 n, d = divmod(n, 2) digits = [d] + digits return digits print bin(69) Примечание: Важно понять, что за именем функции стоит объект. Этот объект можно связать с другим именем: def add(x, y): return x + y addition = add # теперь addition и add — разные имена одного и того же объекта Пример, в котором в качестве значения по умолчанию аргумента функции используется изменчивый объект (список). Этот объект — один и тот же для всех вызовов функций, что может привести к казусам: def mylist(val, lst=[]): lst.append(val) return lst print mylist(1), print mylist(2) Вместо ожидаемого [1] [2] получается [1] [1, 2], так как добавляются элементы к «значению по умолчанию». Правильный вариант решения будет, например, таким: def mylist(val, lst=none): lst = lst or [] lst.append(val) return lst Конечно, приведенная выше форма может использоваться для хранения в функции некоторого состояния между ее вызовами, однако, практически всегда вместо функции с таким побочным эффектом лучше написать класс и использовать его экземпляр. Рекурсия В некоторых случаях описание функции элегантнее всего выглядит с применением вызова этой же функции. Такой прием, когда функция вызывает саму себя, называется рекурсией. В функциональных языках рекурсия обычно используется много чаще, чем итерация (циклы). В следующем примере переписывается функция bin() в рекурсивном варианте: def bin(n): «»»Цифры двоичного представления натурального числа «»» if n == 0: return [] n, d = divmod(n, 2) return bin(n) + [d] print bin(69) Здесь видно, что цикл while больше не используется, а вместо него появилось условие окончания рекурсии: условие, при выполнении которого функция не вызывает себя.

    5 Конечно, в погоне за красивым рекурсивным решением не следует упускать из виду эффективность реализации. В частности, пример реализации функции для вычисления n -го числа Фибоначчи это демонстрирует: def Fib(n): if n >> lst = [1, 2, 3] >>> dct = <'a': 4, 'b': 5>>>> apply(max, lst) 3 >>> max(*lst) 3 >>> apply(dict, [], dct) <'a': 4, 'b': 5>>>> dict(**dct)

    6 Обработка последовательностей Многие алгоритмы сводятся к обработке массивов данных и получению новых массивов данных в результате. Среди встроенных функций Python есть несколько для работы с последовательностями. Под последовательностью в Python понимается любой тип данных, который поддерживает интерфейс последовательности (это несколько специальных методов, реализующих операции над последовательностями, которые в данном курсе обсуждаться не будут). Следует заметить, что тип, основной задачей которого является хранение, манипулирование и обеспечение доступа к самостоятельным данным называется контейнерным типом или просто контейнером. Примеры контейнеров в Python — списки, кортежи, словари. Функции range() и xrange() Функция range() уже упоминалась при рассмотрении цикла for. Эта функция принимает от одного до трех аргументов. Если аргумент всего один, она генерирует список чисел от 0 (включительно) до заданного числа (исключительно). Если аргументов два, то список начинается с числа, указанного первым аргументом. Если аргументов три — третий аргумент задает шаг >>> print range(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> print range(1, 10) [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> print range(1, 10, 3) [1, 4, 7] Функция xrange() — аналог range(), более предпочтительный для использования при последовательном доступе, например, в цикле for или с итераторами. Она возвращает специальный xrange -объект, который ведет себя почти как список, порождаемый range(), но не хранит в памяти все выдаваемые элементы. Функция map() Для применения некоторой функции ко всем элементам последовательности применяется функция map(f, *args). Первый параметр этой функции — функция, которая будет применяться ко всем элементам последовательности. Каждый следующий n+1 -й параметр должен быть последовательностью, так как каждый его элемент будет использован в качестве n -го параметра при вызове функции f(). Результатом будет список, составленный из результатов выполнения этой функции. В следующем примере складываются значения из двух списков: >>> l1 = [2, 7, 5, 3] >>> l2 = [-2, 1, 0, 4] >>> print map(lambda x, y: x+y, l1, l2) [0, 8, 5, 7] В этом примере применена безымянная функция для получения суммы двух операндов ко всем элементам l1 и l2. В случае если одна из последовательностей короче другой, вместо соответствующего операнда будет None, что, конечно, собьет операцию сложения. В зависимости от решаемой задачи, можно либо видоизменить функцию, либо считать разные по длине последовательности ошибкой, которую нужно обрабатывать как отдельную ветвь алгоритма.

    7 Частный случай применения map() — использование None в качестве первого аргумента. В этом случае просто формируется список кортежей из элементов исходных последовательностей: >>> l1 = [2, 7, 5, 3] >>> l2 = [-2, 1, 0, 4] >>> print map(none, l1, l2) [(2, -2), (7, 1), (5, 0), (3, 4)] Функция filter() Другой часто встречающейся операцией является фильтрование исходной последовательности в соответствии с некоторым предикатом (условием). Функция filter(f, seq) принимает два аргумента: функцию с условием и последовательность, из которой берутся значения. В результирующую последовательность попадут только те значения из исходной, для которой f() возвратит истину. Если в качестве f задано значение None, результирующая последовательность будет состоять из тех значений исходной, которые имеют истинностное значение True. Например, в следующем фрагменте кода можно избавится от символов, которые не являются буквами: >>> filter(lambda x: x.isalpha(), ‘Hi, there! I am eating an apple.’) ‘HithereIameatinganapple’ Списковые включения Для более естественной записи обработки списков в Python 2 была внесена новинка: списковые включения. Фактически это специальный сокращенный синтаксис для вложенных циклов for и условий if, на самом низком уровне которых определенное выражение добавляется к списку, например: all_pairs = [] for i in range(5): for j in range(5): if i 8 Функция sum() Получить сумму элементов можно с помощью функции sum(): >>> sum(range(10)) 45 Эта функция работает только для числовых типов, она не может конкатенировать строки. Для конкатенации списка строк следует использовать метод join(). Функция reduce() Для организации цепочечных вычислений (вычислений с накоплением результата) можно применять функцию reduce(), которая принимает три аргумента: функцию двух аргументов, последовательность и начальное значение. С помощью этой функции можно, в частности, реализовать функцию sum(): def sum(lst, start): return reduce(lambda x, y: x + y, lst, start) Совет: Следует помнить, что в качестве передаваемого объекта может оказаться список, который позволит накапливать промежуточные результаты. Тем самым, reduce() может использоваться для генерации последовательностей. В следующем примере накапливаются промежуточные результаты суммирования: lst = range(10) f = lambda x, y: (x[0] + y, x[1]+[x[0] + y]) print reduce(f, lst, (0, [])) В итоге получается: (45, [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]) Функция zip() Эта функция возвращает список кортежей, в котором i -й кортеж содержит i -е элементы аргументов-последовательностей. Длина результирующей последовательности равна длине самой короткой из последовательностей-аргументов: >>> print zip(range(5), «abcde») [(0, ‘a’), (1, ‘b’), (2, ‘c’), (3, ‘d’), (4, ‘e’)] Итераторы Применять для обработки данных явные последовательности не всегда эффективно, так как на хранение временных данных может тратиться много оперативной памяти. Более эффективным решением представляется использование итераторов — специальных объектов, обеспечивающих последовательный доступ к данным контейнера. Если в выражении есть операции с итераторами вместо контейнеров, промежуточные данные не будут требовать много места для хранения — ведь они запрашиваются по мере необходимости для вычислений. При обработке данных с использованием итераторов память будет требоваться только для исходных данных и результата, да и то необязательно вся сразу — ведь данные могут читаться и записываться в файл на диске.

    9 Итераторы можно применять вместо последовательности в операторе for. Более того, внутренне оператор for запрашивает от последовательности ее итератор. Объект файлового типа тоже (построчный) итератор, что позволяет обрабатывать большие файлы, не считывая их целиком в память. Там, где требуется итератор, можно использовать последовательность. Работа с итераторами рассматривается в разделе, посвященном функциональному программированию, так как итераторами удобно манипулировать именно в функциональном стиле. Использовать итератор можно и «вручную». Любой объект, поддерживающий интерфейс итератора, имеет метод next(), который при каждом вызове выдает очередное значение итератора. Если больше значений нет, возбуждается исключение StopIteration. Для получения итератора по некоторому объекту необходимо прежде применить к этому объекту функцию iter() (цикл for делает это автоматически). В Python имеется модуль itertools, который содержит набор функций, комбинируя которые, можно составлять достаточно сложные схемы обработки данных с помощью итераторов. Далее рассматриваются некоторые функции этого модуля. Функция iter() Эта функция имеет два варианта использования. В первом она принимает всего один аргумент, который должен «уметь» предоставлять свой итератор. Во втором один из аргументов — функция без аргументов, другой — стоповое значение. Итератор вызывает указанную функцию до тех пор, пока та не возвратит стоповое значение. Второй вариант встречается много реже первого и обычно внутри метода класса, так как сложно порождать значения «на пустом месте»: it1 = iter([1, 2, 3, 4, 5]) def forit(mystate=[]): if len(mystate) >> print [x for x in enumerate(«abcd»)] [(0, ‘a’), (1, ‘b’), (2, ‘c’), (3, ‘d’)]

    10 Функция sorted() Эта функция, появившаяся в Python 2.4, позволяет создавать итератор, выполняющий сортировку: >>> sorted(‘avdsdf’) [‘a’, ‘d’, ‘d’, ‘f’, ‘s’, ‘v’] Далее рассматриваются функции модуля itertools. Функция itertools.chain() Функция chain() позволяет сделать итератор, состоящий из нескольких соединенных последовательно итераторов. Итераторы задаются в виде отдельных аргументов. Пример: from itertools import chain it1 = iter([1,2,3]) it2 = iter([8,9,0]) for i in chain(it1, it2): даст в результате Функция itertools.repeat() Функция repeat() строит итератор, повторяющий некоторый объект заданное количество раз: for i in itertools.repeat(1, 4): Функция itertools.count() Бесконечный итератор, дающий целые числа, начиная с заданного: for i in itertools.count(1): if i > 100: break

    11 Функция itertools.cycle() Можно бесконечно повторять и некоторую последовательность (или значения другого итератора) с помощью функции cycle(): tango = [1, 2, 3] for i in itertools.cycle(tango): Функции itertools.imap(), itertools.starmap() и itertools.ifilter() Аналогами map() и filter() в модуле itertools являются imap() и ifilter(). Отличие imap() от map() в том, что вместо значения от преждевременно завершившихся итераторов объект None не подставляется. Пример: for i in map(lambda x, y: (x,y), [1,2], [1,2,3]): (1, 1) (2, 2) (None, 3) from itertools import imap for i in imap(lambda x, y: (x,y), [1,2], [1,2,3]): (1, 1) (2, 2) Здесь следует заметить, что обычная функция map() нормально воспринимает итераторы в любом сочетании с итерабельными (поддающимися итерациям) объектами: for i in map(lambda x, y: (x,y), iter([1,2]), [1,2,3]): (1, 1) (2, 2) (None, 3) Функция itertools.starmap() подобна itertools.imap(), но имеет всего два аргумента. Второй аргумент — последовательность кортежей, каждый кортеж которой задает набор параметров для функции (первого аргумента): >>> from itertools import starmap >>> for i in starmap(lambda x, y: str(x) + y, [(1,’a’), (2,’b’)]): a 2b Функция ifilter() работает как filter(). Кроме того, в модуле itertools есть функция ifilterfalse(), которая как бы добавляет отрицание к значению функции: for i in ifilterfalse(lambda x: x > 0, [1, -2, 3, -3]): -2-3

    12 Функции itertools.takewhile() и itertools.dropwhile() Некоторую новизну вносит другой вид фильтра: takewhile() и его «отрицательный» аналог dropwhile(). Следующий пример поясняет их принцип действия: for i in takewhile(lambda x: x > 0, [1, -2, 3, -3]): print for i in dropwhile(lambda x: x > 0, [1, -2, 3, -3]): Таким образом, takewhile() дает значения, пока условие истинно, а остальные значения даже не берет из итератора (именно не берет, а не высасывает все до конца!). И, наоборот, dropwhile() ничего не выдает, пока выполняется условие, зато потом выдает все без остатка. Функция itertools.izip() Функция izip() аналогична встроенной zip(), но не тратит много памяти на построение списка кортежей, так как итератор выдает их строго по требованию. Функция itertools.groupby() Эта функция дебютировала в Python 2.4. Функция принимает два аргумента: итератор (обязательный) и необязательный аргумент — функцию, дающую значение ключа: groupby(iterable[, func]). Результатом является итератор, который возвращает двухэлементный кортеж: ключ и итератор по идущим подряд элементам с этим ключом. Если второй аргумент опущен, элемент итератора сам является ключом. В следующем примере группируются идущие подряд положительные и отрицательные элементы: import itertools, math lst = map(lambda x: math.sin(x*.4), range(30)) for k, i in itertools.groupby(lst, lambda x: x > 0): print k, lst(i) Функция itertools.tee() Эта функция тоже появилась в Python 2.4. Она позволяет клонировать итераторы. Первый аргумент — итератор, подлежащий клонированию. Второй ( N ) — количество необходимых копий. Функция возвращает кортеж из N итераторов. По умолчанию N=2. Функция имеет смысл, только если итераторы задействованы более или менее параллельно. В противном случае выгоднее превратить исходный итератор в список.

    13 Собственный итератор Для полноты описания здесь представлен пример итератора, определенного пользователем. Если пример не очень понятен, можно вернуться к нему после изучения объектно-ориентированного программирования: реализацией. Ленивыми называются вычисления, которые откладываются до самого последнего момента, когда получаемое в результате значение сразу используется в другом вычислении. Для примера с последовательностью Фибоначчи можно построить такой вот генератор: def Fib(N): a, b = 0, 1 for i in xrange(n): yield a a, b = b, a + b Использовать его не сложнее, чем любой другой итератор: for i in Fib(100): Однако следует заметить, что программа в значительной степени упростилась.

    14 Генераторное выражение В Python 2.4 по аналогии со списковым включением появилось генераторное выражение. По синтаксису оно аналогично списковому, но вместо квадратных скобок используются круглые. Списковое включение порождает список, а, значит, можно ненароком занять очень много памяти. Генератор же, получающийся в результате применения генераторного выражения, списка не создает, он вычисляет каждое следующее значение строго по требованию (при вызове метода next() ). В следующем примере можно прочесть из файла строки, в которых производятся некоторые замены: for line in (l.replace(«- «, » — «) for l in open(«input.dat»)): print line Ничто не мешает использовать итераторы и для записи в файл: open(«output.dat», «w»).writelines( l.replace(«- «, » — «) for l in open(«input.dat»)) Здесь для генераторного выражения не потребовалось дополнительных скобок, так как оно расположено внутри скобок вызова функции. Карринг Библиотека Xoltar toolkit (автор Bryn Keller) включает модуль functional, который позволяет упростить использование возможностей функционального программирования. Модуль functional применяет «чистый» Python. Библиотеку можно найти по этому адресу. При карринге (частичном применении) функции создается новая функция, задавая некоторые аргументы исходной. Следующий пример иллюстрирует частичное применение вычитания: from functional import curry def subtract(x, y): return x — y print subtract(3, 2) subtract_from_3 = curry(subtract, 3) print subtract_from_3(2) print curry(subtract, 3)(2) Во всех трех случаях будет выведено 1. В следующем примере получается новая функция, подставляя второй аргумент. Вместо другого аргумента вставляется специальное значение Blank: from functional import curry, Blank def subtract(x, y): return x — y print subtract(3, 2) subtract_2 = curry(subtract, Blank, 2) print subtract_2(3) print curry(subtract, Blank, 2)(3)

    15 Заключение В этой лекции рассматривался принцип построения функциональных программ. Кроме того, было показано, что в Python и его стандартных модулях имеются достаточно мощные выразительные средства для создания функциональных программ. В случае, когда требуются дополнительные возможности, например, карринг, их можно легко реализовать или взять готовую реализацию. Следует отметить, что итераторы — это практичное продолжение функционального начала в языке Python. Итераторы по сути позволяют организовать так называемые ленивые вычисления (lazy computations), при которых значения вычисляются только когда они непосредственно требуются.

    Мастер Йода рекомендует:  Создание CSS-анимации при помощи Move.js
    Добавить комментарий