Х 4 3х 4 2: Решите уравнение х^4=(3х-4)^2 — ответ на Uchi.ru

Мир Python: функционалим по-маленьку | Python для продвинутых

Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Введение

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

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

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

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

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

  • Функции высшего порядка
  • Чистые функции
  • Неизменяемые данные

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

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

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

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

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

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

Плюсы:

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

Неизменяемые данные

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

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

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

theory-source

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

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

def f(x):
    return x + 3
def g(function, x):
    return function(x) * function(x)
print(g(f, 7))

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

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

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

Пример кода:

for x in xrange(5, 10):
    if x % 2 == 0:
        x =* 2
    else:
        x += 1

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

>>> [x * 2 if x % 2 == 0 else x + 1 for x in xrange(5, 10)]
[6, 12, 8, 16, 10]

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

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

[stmt for var in iterable if predicate] 

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

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

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

Функция:

def calc(x, y):
    return x**2 + y**2

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

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

>>> lambda x, y: x**2 + y**2
<function <lambda> at 0x7fb6e34ce5f0>

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

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

Пример:

>>> (lambda x, y: x**2 + y**2)(1, 4)
17
>>>
>>> func = lambda x, y: x**2 + y**2
>>> func(1, 4)
17

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

multiplier = lambda n: lambda k: n*k

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

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

map()

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

>>> list1 = [7, 2, 3, 10, 12]
>>> list2 = [-1, 1, -5, 4, 6]
>>> list(map(lambda x, y: x*y, list1, list2))
[-7, 2, -15, 40, 72]

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

>>> [x*y for x, y in zip(list1, list2)]
[-7, 2, -15, 40, 72]

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

filter()

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

>>> numbers = [10, 4, 2, -1, 6]
>>> list(filter(lambda x: x < 5, numbers))     # В результат попадают только те элементы x, для которых x < 5 истинно
[4, 2, -1]

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

>>> numbers = [10, 4, 2, -1, 6]
>>> [x for x in numbers if x < 5]
[4, 2, -1]

reduce()

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

>>> numbers = [2, 3, 4, 5, 6]
>>> reduce(lambda res, x: res*x, numbers, 1)
720

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

((((1*2)*3)*4)*5)*6

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

>>> reduce(lambda res, x: res*x, [], 1)
1

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

>>> reduce(lambda res, x: [x]+res, [1, 2, 3, 4], [])
[4, 3, 2, 1]

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

>>> numbers = [1, 2, 3, 4, 5]
>>> sum(numbers)
15
>>> list(reversed(numbers))
[5, 4, 3, 2, 1]

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

apply()

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

>>> def f(x, y, z, a=None, b=None):
...     print x, y, z, a, b
...
>>> apply(f, [1, 2, 3], {'a': 4, 'b': 5})
1 2 3 4 5

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

>>> def f(x, y, z, a=None, b=None):
...     print(x, y, z, a, b)
...
>>> f(*[1, 2, 3], **{'a': 4, 'b': 5})
1 2 3 4 5

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

Замыкания

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

Код (вымышленный):

def processing(element, type_filter, all_data_size):
    filters = Filter(all_data_size, type_filter).get_all()
    for filt in filters:
        element = filt.
filter(element) def main(): data = DataStorage().get_all_data() for x in data: processing(x, 'all', len(data))

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

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

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

def multiplier(n):
    "multiplier(n) возвращает функцию, умножающую на n" 
    def mul(k): 
        return n*k 
     return mul 
     # того же эффекта можно добиться выражением 
     # multiplier = lambda n: lambda k: n*k 
mul2 = multiplier(2) # mul2 - функция, умножающая на 2, например, 
mul2(5) == 10

Заключение

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


Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

4. Условия подведения итогов \ КонсультантПлюс

4. Условия подведения итогов

1. Спортивные соревнования в дисциплине «городки классические» проводятся на 90 фигур в три тура из двух партий по 15 фигур в каждом туре. Проходной норматив во 2 и 3 туры 54 и 108 бросков соответственно.

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

— последнего тура;

— последней партии последнего тура;

— предпоследнего тура;

— «Пулеметное гнездо», «Часовые», «Тир», «Письмо» во всех партиях соревнований.

2. Спортивные соревнования в дисциплине «городки классические — командные соревнования» проводятся по круговой системе. Встречи проводятся из 3-х партий по 15 фигур. Количество очков, начисляемых во встрече: выигрыш — 2, ничья — 1, проигрыш — 0.

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

— по сумме очков, набранных в играх между ними;

— по разности выигранных и проигранных партий в играх между ними;

— по лучшему среднему техническому результату в выигранных и ничейных партиях в играх между ними;

— по разности выигранных и проигранных партий во всех играх соревнований;

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

3. Спортивные соревнования в дисциплине «городки европейские» проводятся в два этапа.

Первый этап:

Спортсмены играют две партии по 15 фигур 20 бросками каждая, вместо фигуры «Письмо» — фигура «Факс».

Первая партия играется, начиная с «Пушки», вторая — с «Факса» в обратном порядке. Два спортсмена, выбившие большее количество городков на первом этапе разыгрывают 1 и 2 место во втором этапе. Спортсмены, показавшие 3 и 4 результаты на первом этапе, разыгрывают 3 место. Места остальных участников определяются по результату первого этапа.

Второй этап:

Участники играют по 6 фигур в партии (первая партия — фигуры N 1, 2, 3, 4, 5, «Факс», 2 партия — фигуры N 6, 7, 8, 9, 10, «Факс», третья партия — N 11, 12, 13, 14, 15, «Факс») до двух выигранных партий. В случае ничейного результата после трех партий играется дополнительная партия до первого преимущества на какой-либо фигуре.

4. Спортивные соревнования в дисциплине «городки европейские — командные соревнования» проводятся в два этапа:

Первый этап:

В первом этапе команды играют две партии по 15 фигур 18 бросками каждая, вместо фигуры «Письмо» — фигура «Факс». Первая партия играется, начиная с «Пушки», вторая — с «Факса» в обратном порядке. Две команды, выбившие большее количество городков на первом этапе разыгрывают 1 и 2 место во втором этапе, команды, показавшие 3 и 4 результаты на первом этапе, разыгрывают 3 место во втором этапе. Места остальных команд определяются по результатам первого этапа.

Второй этап:

Во втором этапе команды играют по 10 фигур в партии (фигуры N 1, 2, 5, 6, 7, 9, 11, 13, 15 и «Факс») до двух выигранных партий. В случае ничейного результата после трех партий играется дополнительная партия до первого преимущества на какой-либо из фигур.

5. Спортивные соревнования в спортивной дисциплине «городки финские — кюккя» проводятся в два этапа:

Первый этап:

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

Второй этап:

Разбивка на пары во втором этапе производится согласно результатам, показанным в первом этапе (1 — 2, 3 — 4). Места спортсменов определяются по результатам, показанным во втором этапе. Соревнования проводятся аналогично первому этапу.

Спортсменам, показавшим в первом этапе соревнований результат +13 — у мужчин и +10 — у женщин, предоставляется право продолжить соревнования в еще одном туре с определением мест с 5-го и далее. Места участников, не уложившихся в установленный норматив, определяются по результатам первого этапа.

6. Спортивные соревнования в спортивной дисциплине «городки финские — кюккя — командные соревнования» проводятся по смешанной системе в два этапа:

Первый этап:

В первом этапе команды играют для выявления четверки сильнейших. Каждая команда играет две партии, в которых выбивает по 20 городков не более чем 24-мя бросками. Очки за городки, не выбитые 24-мя бросками, суммируются со знаком «-» по правилам соревнований. Очки за невыполненные броски, оставшиеся после выбивания всех 20-ти городков партии (из 24 данных бросков) — со знаком «+». Участники, набравшие большую сумму очков, занимают более высокие места. В случае равенства набранных очков, места определяются по правилам соревнований.

Второй этап:

Команды, занявшие в первом этапе первые четыре места играют в полуфиналах (1 — 4, 2 — 3), а затем, победители — в финале, а проигравшие — в игре за 3 место.

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

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

7. Итоговые результаты (протоколы) и отчеты на бумажном и электронном носителях представляются в Минспорт России и ФГБУ «ЦСП» в течение двух недель со дня окончания спортивного соревнования.

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

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