yield
operator# encoding: utf-8 def get_writer (type, params): # data output in HTML def html_writer (filename): f = open (filename + '.' + type, 'w'); f.write ("" " <html> <head> <title>% s </ title> </ head> <body> <h1> Hello </ h1> </ body> "" "% params ['title']) f.close () # data output to PLAIN TEXT def text_writer (filename): f = open (filename + '.' + type, 'w'); f.write ("" " % s ================================= Hello "" ") f.close () # determine which data type was requested and return the corresponding function if type == 'html': return html_writer elif type == 'txt': return text_writer params = {'title': 'Header'} # print HTML f = get_writer ('html', params) f ('file1') # we put in PLAIN TEXT f = get_writer ('txt', params) f ('file2')
html_writer
and text_writer
, the get_writer
( type
and params
) arguments are used. How can this be? After all, after returning from get_writer
its arguments, in theory, cease to exist? This is the essence of the closure: if one function returns another, then the so-called context is added to the latter - the set of all available variables (local, global, arguments) with their values at the time of the call. Thus, when returning a function from a function, you return not just a function (sorry for tautology), but a closure - a function + context.# encoding: utf-8 import math # y = k * x + b def get_linear (k, b): return lambda x: k * x + b # y = k * x ^ 2 + b def get_sqr (k, b): return lambda x: k * x ** 2 + b # y = A * sin (k * x + phi) def get_sin (amplitude, phi, k): return lambda x: amplitude * math.sin (math.radians (k * x + phi)) # y = A * e ^ (k * x) def get_exp (amplitude, k, b): return lambda x: amplitude * math.exp (k * x + b)
# y = 5 * sin (0.3 * x + 30) y = get_sin (5, 30, 0.3) # y (90) = 4.19 print y (90) print # the result of applying y to the interval from 0 to 180 print [y (x) for x in range (0, 180)]
def shifter (func, b): return lambda x: func (x + b) def x_scaler (func, k): return lambda x: func (k * x) def y_scaler (func, A): return lambda x: A * func (x) def combine (func1, func2): return lambda x: func2 (func1 (x))
shifter
, x_scaler
, y_scaler
, combine
are high-order functions, because they take not only scalar arguments, but also other functions, modifying their behavior. Combine
is an extremely useful general function that allows you to apply one function to another. Now we can rewrite our previous functions as follows:def identity (x): return x def sqr (x): return x ** 2
identity
- the function of identity is a very important concept in the OP. Very important, but very simple - returns its argument and all. The second function simply squares the argument. Now we can get any configuration that we could describe with our functions from the first example by combining simple functions and higher order functions — the main thing is to combine them in the correct sequence. To demonstrate what it means in the correct sequence, I will give the following expression:y = x_scaler (shifter (x_scaler (sqr, 5), 6), 7)
x_scaler(5)
and not sqr
, but the outermost x_scaler
. Then the shifter
. then the internal x_scaler
. Then sqr
. Twist it a little in your head, you need to get used to it a little. The order is this: the outermost modifier is applied first . The result will be completely analogous to the following function:def y (x): return sqr (((x * 7) + 6) * 5)
# y_scaler (5) should be the most recent y = y_scaler (math.sin, 5) # 2 last is turning angle to radians y = combine (math.radians, y) # further - shifter (30) y = shifter (y, 30) # finally - x_scaler (0.3) y = x_scaler (y, 0.3)
def modulate (mod, src): return lambda x: mod (x) * src (x)
# y1 = 5 * sin (15 * x + 30) - the original function y1 = \ x_scaler ( shifter ( combine ( math.radians, y_scaler ( math.sin five)), thirty), 15) # y2 = exp (-0.01 * x) - modulating function y2 = x_scaler (math.exp, -0.01) y = modulate (y2, y1) print [y (x) for x in range (0, 180)]
Source: https://habr.com/ru/post/49723/
All Articles