Уведомления

Группа в Telegram: @pythonsu

#1 Июль 2, 2020 20:34:14

Azart
Зарегистрирован: 2020-05-09
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

объясните плиз как работает эта функция!!!

Решаю задачки на codewars нужно написать калькулятор из вложенных функций по примеру:
seven(times(five())) # must return 35
four(plus(nine())) # must return 13
eight(minus(three())) # must return 5
six(divided_by(two())) # must return 3

подсмотрел решение:

 def zero(f = None): return 0 if not f else f(0)
def one(f = None): return 1 if not f else f(1)
def two(f = None): return 2 if not f else f(2)
def three(f = None): return 3 if not f else f(3)
def four(f = None): return 4 if not f else f(4)
def five(f = None): return 5 if not f else f(5)
def six(f = None): return 6 if not f else f(6)
def seven(f = None): return 7 if not f else f(7)
def eight(f = None): return 8 if not f else f(8)
def nine(f = None): return 9 if not f else f(9)
def plus(y): return lambda x: x+y
def minus(y): return lambda x: x-y
def times(y): return lambda  x: x*y
def divided_by(y): return lambda  x: x/y
Можете разжевать как этот код работает?
не понимаю вот это f= Noone и почему возвращается f(число) ???
также с lambda x: x+y откуда функция берет значение х ???

Офлайн

#2 Июль 2, 2020 23:46:13

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2682
Репутация: +  182  -
Профиль   Отправить e-mail  

объясните плиз как работает эта функция!!!

Да тут всё очень просто:
Функции zero - nine должны принимать либо None либо унарную функцию f. Если пришло None, то возвращается соответствующая цифра, иначе возвращается результат вызова функции f на соответствующем значении.
Функции plus, minus, times, divided_by как раз и возвращает функцию f. f должна быть унарной функцией, но операторы бинарны, по этому нужно уменьшить их арность. Это достигается за счёт каррирования.

Вот как это используется:
> six(divided_by(two()))

1) two() - возвращает 2
2) divided_by(2) - возвращает унарную функцию (a -> b). Она делит переданное ей значение на 2.
3) six((a -> b)) - (a -> b)(6) - 6/2=3



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

Отредактировано Rodegast (Июль 2, 2020 23:51:53)

Офлайн

#3 Июль 3, 2020 00:42:21

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9726
Репутация: +  843  -
Профиль   Отправить e-mail  

объясните плиз как работает эта функция!!!

Тут решение и потом объяснение

  
>>> def zero(func=None):
...     return 0 if func is None else func(0)
... 
>>> def one(func=None):
...     return 1 if func is None else func(1)
... 
>>> def two(func=None):
...     return 2 if func is None else func(2)
... 
>>> def three(func=None):
...     return 3 if func is None else func(3)
... 
>>> def four(func=None):
...     return 4 if func is None else func(4)
... 
>>> def five(func=None):
...     return 5 if func is None else func(5)
... 
>>> def six(func=None):
...     return 6 if func is None else func(6)
... 
>>> def seven(func=None):
...     return 7 if func is None else func(7)
... 
>>> def eight(func=None):
...     return 8 if func is None else func(8)
... 
>>> def nine(func=None):
...     return 9 if func is None else func(9)
... 
>>> def plus(num):
...     return lambda x: x + num
... 
>>> def minus(num):
...     return lambda x: x - num
... 
>>> def times(num):
...     return lambda x: x * num
... 
>>> def divided_by(num):
...     return lambda x: x // num
... 
>>> seven(times(five())) # must return 35
35
>>> 
>>> four(plus(nine())) # must return 13
13
>>> 
>>> eight(minus(three())) # must return 5
5
>>> 
>>> six(divided_by(two())) # must return 3
3
>>>


Azart
не понимаю вот это f= Noone и почему возвращается f(число) ?
На примере вызовов
  
seven(times(five()))
Как видишь, в функцию seven() что-то подаётся. Поэтому у функции seven() должен быть какой-то аргумент. Функция five() имеет такое же устройство, как и функция seven(), отличается только цифра - 5 или 7. Но в функцию five() ничего не подаётся. Поэтому у функции five() не должно быть аргумента. Раз они одинаковые по устройству, но аргумент то подаётся, то не подаётся, это надо как-то обработать.

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

Пример функции с именованным аргументом
  
>>> def f(x=2):
...     return x * 2
... 
>>> f()
4
>>> f(3)
6
>>> f(4)
8
>>>
Если значение аргумента при вызове функции не задано, то берётся значение аргумента по умолчанию. Если значение аргумента при вызове функции задано, то берётся переданное значение аргумента.

В случае этой задачи в топике, значение аргумента по умолчанию равно None. None - это такая формализованная “пустота” в питоне. Если что-то пусто, мы ему придаём значение None.

Ещё раз говорю: прочитай учебник по питону, чтобы тебе на разных форумах не переписывали страницы из учебников по питону.

Когда в функцию seven() ничего не подаётся, она просто возвращает число семь. Когда в функцию seven() подаётся функция, функция seven() применяет эту переданную функцию к числу 7.

Пример с функцией seven() :

Тут создаём вторую функцию, чтобы на ней подробно всё расссмотреть
  
>>> def seven(func=None):
...     return 7 if func is None else func(7)
... 
>>>
>>> def multiply10(x):
...     return x * 10
... 
>>>
>>> multiply10(5)
50
>>> multiply10(7)
70
>>> multiply10(12)
120
>>>
>>> seven()
7
>>> seven(multiply10)
70
>>>

Тут создаём функцию на лету
  
>>> def seven(func=None):
...     return 7 if func is None else func(7)
... 
>>> seven()
7
>>> seven(lambda x: x * 10)
70
>>>
Функция, аналогичная функции multiply10(), создалась на лету, передалась в вызов функции seven(), после этого отработала там внутри (дала результат функции seven(), чтобы та его возвращала наружу потом) и сразу уничтожилась.



Azart
также с lambda x: x+y откуда функция берет значение х ?
Дальше используется ещё одно понятие - замыкание. Замыкание - это такой приём, когда функция замыкается внутри функции и в таком состоянии возвращается наружу.

Замыкание может использоваться, чтобы динамически создавать функции, которые проделывают какой-то набор одних и тех же действий но над разными числами, которые передают в эти функции. Например, “замыкание на умножение на десятку” замкнуто так, что любое передаваемое в функцию число будет умножено на десять. Например, “замыкание на добавление строки в файл” замкнуто так, что любой передаваемый в функцию файловый объект будет на низком уровне открываться на запись и туда будет добавляться строка. Замыкания можно делать произвольными - с любыми объектами, с любыми действиями.

Пример замыкания
Тут замыкание на умножение на десятку, замыкание на умножение на двадцатку, замыкание на умножение на одиннадцать
  
>>> def multiply(times):
...     def f(x):
...         return times * x
...     return f
... 
>>> mul10 = multiply(10)
>>> mul20 = multiply(20)
>>> mul11 = multiply(11)
>>> 
>>> mul10(5)
50
>>> mul10(6)
60
>>> mul10(10)
100
>>> 
>>> mul20(5)
100
>>> mul20(6)
120
>>> mul20(10)
200
>>> 
>>> mul11(5)
55
>>> mul11(6)
66
>>> mul11(10)
110
>>>

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

Пример замыкания без аргументов
  
>>> def number(num):
...     def f():
...         return num
...     return f
... 
>>> num7 = number(7)
>>> num25 = number(25)
>>> num10 = number(10)
>>> 
>>> num7()
7
>>> num7()
7
>>> 
>>> num25()
25
>>> num25()
25
>>> 
>>> num10()
10
>>> num10()
10
>>>

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

Пример с функцией plus() :

Тут создаём операцию сложения в развёрнутом виде, чтобы на ней подробно всё расссмотреть
  
>>> def plus(a):
...     def f(b):
...         return a + b
...     return f
... 
>>> plus10 = plus(10)
>>> plus20 = plus(20)
>>> plus11 = plus(11)
>>> 
>>> plus10(15)
25
>>> plus10(20)
30
>>> plus10(1)
11
>>> 
>>> plus20(15)
35
>>> plus20(20)
40
>>> plus20(1)
21
>>> 
>>> plus11(15)
26
>>> plus11(20)
31
>>> plus11(1)
12
>>>

Выше в коде с решением, который я отправил первым, ты видишь то же самое замыкание.
  
>>> def plus(num):
...     return lambda x: x + num
... 
>>>
Отличие только в том, что аргумент a называется num, аргумент b называется x и функция, которая замыкается и возвращается наружу, создаётся не через полноценное определение функции, а на лету с помощью конструкции lambda.

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



Отредактировано py.user.next (Июль 3, 2020 00:58:43)

Офлайн

#4 Июль 3, 2020 22:46:36

Azart
Зарегистрирован: 2020-05-09
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

объясните плиз как работает эта функция!!!

Огромное спасибо за ответы, сижу вникаю!!!

py.user.next
Ещё раз говорю: прочитай учебник по питону, чтобы тебе на разных форумах не переписывали страницы из учебников по питону.
Да уже прочитал пару книжек, сейчас Марка Лутца читаю, но я на 300й странице из 1500 , попутно решаю вот такие простенькие задачки. Просто наткнулся на эту и захотел понять как это работает, хотя понимаю что знаний пока не достаточно, нужно читать книги!) Еще раз большое спасибо за подробное разъяснение!

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version