Основная часть
Эту часть практических вопросов нужно успеть сделать на занятии.
|
Проверять правильность ответов на ПСП-вопросы можно и нужно из терминала вот таким образом:
Если что-то не так, будет выведено сообщение об ошибке с указанием функции и номера строки в файле. |
Вопрос 1: Лямбда-выражения (ПСП)
Подумай и запиши, что выведет Python при обработке следующих выражений.
|
Если значение выражения является функцией, то вывод интерпретатора будет примерно такой:
|
>>> lambda x: x
______
>>> a = lambda x: x
>>> a(5)
______
>>> b = lambda: 3
>>> b()
______
>>> c = lambda x: lambda: print('123')
>>> c(88)
______
>>> c(88)()
______
>>> d = lambda f: f(4)
>>> def square(x):
... return x * x
>>> d(square)
______
>>> z = 3
>>> e = lambda x: lambda y: lambda: x + y + z
>>> e(0)(1)()
______
>>> f = lambda z: x + z
>>> f(3)
______
>>> higher_order_lambda = lambda f: lambda x: f(x)
>>> g = lambda x: x * x
>>> higher_order_lambda(2)(g)
______
>>> higher_order_lambda(g)(2)
______
>>> call_thrice = lambda f: lambda x: f(f(f(x)))
>>> call_thrice(lambda y: y + 1)(0)
______
>>> print_lambda = lambda z: print(z)
>>> print_lambda
______
>>> one_thousand = print_lambda(1000)
______
>>> one_thousand
______
|
Помнишь?
|
Вопрос 2: Функции высшего порядка (ПСП)
>>> def even(f):
... def odd(x):
... if x < 0:
... return f(-x)
... return f(x)
... return odd
>>> janet = lambda x: x
>>> brad = even(janet)
>>> brad
______
>>> brad(61)
______
>>> brad(-4)
______
>>> def cake():
... print('гадость')
... def pie():
... print('сладость')
... return 'торт'
... return pie
>>> chocolate = cake()
______
>>> chocolate
______
>>> chocolate()
______
>>> more_chocolate, more_cake = chocolate(), cake
______
>>> more_chocolate
______
>>> def snake(x, y):
... if cake == more_cake:
... return lambda: x + y
... else:
... return x + y
>>> snake(10, 20)
______
>>> snake(10, 20)()
______
>>> cake = 'торт'
>>> snake(10, 20)
______
|
Не забывай.
|
Вопрос 3: Каррирование лямбдой
|
Проверять правильность кода в следующих вопросах нужно так:
|
Функцию множества аргументов можно превратить в цепочку функций высшего порядка, каждая из которых — функция одного аргумента.
Напиши функцию lambda_curry2, которая будет производить такое преобразование для функции двух аргументов. Посмотри на доктест, если задание не очень понятно. Решение должно занимать всего одну строку.
| Можешь сначала решить задачу без ограничения по размеру кода, а потом, когда логика будет понятна, переписать как требуется. |
def lambda_curry2(func):
"""
Возвращает каррированную версию функции func от двух аргументов.
>>> from operator import add
>>> x = lambda_curry2(add)
>>> y = x(3)
>>> y(5)
8
"""
return ______
|
Обязательно.
|
Вопрос 4: Лямбды на диаграммах окружения
Попробуй нарисовать диаграмму окружения для следующего фрагмента кода и предугадать, что получится в итоге.
Решение этого задания не нужно заносить в файл lab_02.py. Просто нарисуй диаграмму окружения на листе бумаги, а потом проверь себя с помощью сайта Online Python Tutor.
>>> a = lambda x: x * 2 + 1
>>> def b(b, x):
... return b(x + a(x))
>>> x = 3
>>> b(a, x)
______
Дополнительная часть
Эту часть, если есть время, можно поделать и дома.
Вопрос 5: Равенство композиции
Напиши функцию, которая принимает две функции одного аргумента — f и g — и возвращает другую функцию одного аргумента x. Эта функция должна возвращать True, если f(g(x)) и g(f(x)) равны. Можешь считать, что результат g(x) можно использовать аргументом для f и наоборот.
Попробуй в решении использовать compose1, приведённую ниже для справки.
|
def compose1(f, g):
"""
Возвращает функцию h такую, что h(x) = f(g(x)).
>>> add_one = lambda x: x + 1 # прибавляет единицу к x
>>> square = lambda x: x**2
>>> a1 = compose1(square, add_one) # (x + 1)^2
>>> a1(4)
25
>>> mul_three = lambda x: x * 3 # умножает 3 на x
>>> a2 = compose1(mul_three, a1) # ((x + 1)^2) * 3
>>> a2(4)
75
>>> a2(5)
108
"""
return lambda x: f(g(x))
def composite_identity(f, g):
"""
Возвращает функцию одного аргумента, которая возвращает True,
если f(g(x)) равно g(f(x)). Можешь считать, что результат g(x)
может быть аргументом f, и наоборот.
>>> add_one = lambda x: x + 1 # прибавляет единицу к x
>>> square = lambda x: x**2
>>> b1 = composite_identity(square, add_one)
>>> b1(0) # (0 + 1)^2 == 0^2 + 1
True
>>> b1(4) # (4 + 1)^2 != 4^2 + 1
False
"""
"*** ТВОЙ КОД ЗДЕСЬ ***"
|
Уже надоело напоминать.
|
Вопрос 6: Считать-непересчитать
Рассмотри две функции count_factors и count_primes.
def count_factors(n):
"""Возвращает количество положительных целых делителей n."""
i, count = 1, 0
while i <= n:
if n % i == 0:
count += 1
i += 1
return count
def count_primes(n):
"""Возвращает число простых чисел, встречающихся до и включая n."""
i, count = 1, 0
while i <= n:
if is_prime(i):
count += 1
i += 1
return count
Код этих функций сильно похож. Нужно обобщить логику подсчёта и написать функцию count_cond, которая принимает функцию двух аргументов condition(n, i). Функция count_cond должна вернуть функцию одного аргумента n, которая подсчитывает количество целых чисел от 1 до n, которые удовлетворяют условию condition.
def count_cond(condition):
"""
Возвращает функцию одного аргумента N, которая подсчитывает все числа от 1 до N,
для которых выполняется предикат condition — функция двух аргументов.
>>> count_factors = count_cond(lambda n, i: n % i == 0)
>>> count_factors(2) # 1, 2
2
>>> count_factors(4) # 1, 2, 4
3
>>> count_factors(12) # 1, 2, 3, 4, 6, 12
6
>>> is_prime = lambda n, i: count_factors(i) == 2
>>> count_primes = count_cond(is_prime)
>>> count_primes(2) # 2
1
>>> count_primes(3) # 2, 3
2
>>> count_primes(4) # 2, 3
2
>>> count_primes(5) # 2, 3, 5
3
>>> count_primes(20) # 2, 3, 5, 7, 11, 13, 17, 19
8
"""
"*** ТВОЙ КОД ЗДЕСЬ ***"
|
Вошло в привычку?
|
Вопрос 7: Тебе же правда нравятся функции
Напиши функцию cycle, которая принимает три функции — f1, f2 и f3. Функция cycle должна вернуть другую функцию, которая принимает единственный аргумент n и возвращает ещё более другую функцию. Последняя должна принимать аргумент x и циклически применять к нему функции f1, f2 и f3 столько раз, каково значение n.
Вот что должно получаться:
-
n = 0→ возвращаетx; -
n = 1→ возвращаетf1(x); -
n = 2→ возвращаетf2( f1(x) ); -
n = 3→ возвращаетf3( f2( f1(x) ) ); -
n = 4→ (цикл начинается сначала), возвращаетf1( f3( f2( f1(x) ) ) ); -
и так далее.
def cycle(f1, f2, f3):
"""Возвращает функцию, которая является функцией высшего порядка.
>>> def add1(x):
... return x + 1
>>> def times2(x):
... return x * 2
>>> def add3(x):
... return x + 3
>>> my_cycle = cycle(add1, times2, add3)
>>> identity = my_cycle(0)
>>> identity(5)
5
>>> add_one_then_double = my_cycle(2)
>>> add_one_then_double(1)
4
>>> do_all_functions = my_cycle(3)
>>> do_all_functions(2)
9
>>> do_more_than_a_cycle = my_cycle(4)
>>> do_more_than_a_cycle(2)
10
>>> do_two_cycles = my_cycle(6)
>>> do_two_cycles(1)
19
"""
"*** ТВОЙ КОД ЗДЕСЬ ***"
|
Не забудь отправить работу на проверку:
|