Higher order functions

 recursive function

            The advantage of using recursive functions is that the logic is simple and clear, and the disadvantage is that too deep calls can lead to stack overflow.
            Languages ​​optimized for tail recursion can prevent stack overflows by tail recursion. Tail recursion is actually equivalent to looping. Programming languages ​​without looping statements can only implement looping through tail recursion.
            The python interpreter is not optimized for tail recursion, and any recursive function has the problem of stack overflow.
            
            Ordinary recursive function:
                def fact(n):
                    if n == 1:
                        return 1
                    return n * fact(n-1)
            Tail recursive:
                def fact(n):
                    return fact_iter(n, 1)
                def fact_iter(num, product) :
                    if num == 1:
                        return product
                    return fact_iter(num-1, num * product)
            When tail-recursive calls are made, the stack will not grow if optimized, so no matter how many calls it will not cause stack overflow.
            Unfortunately, most programming languages ​​are not optimized for tail recursion, nor is the python interpreter optimized, so even changing the above fact(n) function to tail recursion will cause a stack overflow.

   

 Higher order functions


        A function itself can also be assigned to a variable, that is: a variable can point to a function. Equivalent to giving a function a distinguished name.
        For example: a=abs
            a(-10) and abs(-10) have the same effect.
        A function name is actually a variable that points to the function. So you can make the function name point to other data.
        For example: abs = 10 #The function name abs points to the integer 10, then calling abs(-10) will report an error, because abs no longer points to the absolute value function.
        
        Since variables can point to functions, and function parameters can receive variables, then a function can receive another function as a parameter. This kind of function is called a higher-order function.
        Writing higher-order functions is to allow the parameters of the function to receive other functions.
        Such as: def add(x, y, func):
                return func(x) + func(y)
            call: add(-4 , 6, abs) #10

        
        map(f, iterable):
                The map function receives two parameters, one is a function and the other is an Iterable. The map applies the incoming function to each function of the sequence in turn, and returns the result as a new Iterator.
                The first parameter passed in by map() is f, which is the function object itself. Since the result r is an Iterator, which is a lazy sequence, you can use the list() function to make it calculate the entire sequence and return a list.
                Such as: list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9, 0])) # Convert all numbers in list to characters: ['1','2', '3','4','5','6','7','8','9','0']
        
        reduce():
                The reduce() function applies a function to a sequence [x1, x2, x3, x4,....], this function must accept two parameters, reduce continues the result and accumulates the next element of the sequence.
                The effect is: reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
                from functools import reduce
                DIGITS = {'0':0, '1' :1, '2':2, '3':3, '4':4, '5':5,

                    def fn(x, y):
                        return x * 10 + y
                    def char2num(s):
                        return DIGITS[s]
                    return reduce(fn, map(char2num, s))
            
                或者:
                from functools import reduce
                DIGITS = {'0':0, '1':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9}
                def char2num(s):
                    return DIGITS[s]
                def str2int(s):
                    return reduce(lamdba x, y:x*10+y, map(char2num, s))

        filter():
            Similar to map(), filter() is used to filter sequences and also accepts a function and a sequence. Unlike map(), filter() applies the incoming function to each element in turn, and then decides to keep or discard the element according to whether the return value is True or False.
            filter() is a higher-order function, and the key is to implement a filter function correctly. The filter() function returns an Iterator, which is a lazy sequence, so to force filter() to complete the calculation results, you need to use the list() function to get all the results and return a list.
            The function of filter() is to filter out qualified elements from a sequence. Since filter() uses lazy calculation, only when the result of filter() is taken, will it really filter and return the next screened out each time element.
            
            Example: get primes
            def _odd_iter():
                n = 1
                while True:
                    n = n + 2
                    yield n
                    
            def _not_divisible(n):
                return lambda x:x % n > 0
            
            def primes():
                yield 2
                it = _odd_iter()
                while True:
                    n = next(it)
                    yield n
                    it = filter(_not_divisible(n), it)
            
            primes() is also an infinite sequence, so the call needs to set a condition to exit the loop.
            
        
        sorted():
            sorted() is also a high-order function that can accept a list and a key function to implement custom sorting.
            The function specified by key will act on each element of the list and sort according to the result returned by the key function.
            When sorting strings, key=str.lower() can ignore case. To perform reverse sorting, the key function does not need to be changed, and the third parameter reverse = True can be passed in.

                    
  return function

            In addition to accepting functions as parameters, higher-order functions can also return functions as result values.
            One thing to keep in mind when returning a closure: the returning function does not refer to any loop variables, or variables that will change later.
    
  

 anonymous function

            The keyword lambda represents an anonymous function, and the x before the colon represents a function parameter.
            An anonymous function has a limitation, that is, there can only be one expression, no need to write return, the return value is the result of the expression.
            There is an advantage to using anonymous functions, because functions don't have names, and you don't have to worry about function name collisions. In addition, an anonymous function is also a function object. You can also assign an anonymous function to a variable, and then use the variable to call the function.
            Likewise, anonymous functions can also be returned as return values.
            For example: f = lambda x:x*x
                def build(x, y):
                    return lambda: x *x +y * y
            Python has limited support for anonymous functions, and anonymous functions can be used only in some simple cases.
            

partial function

functools.partial is used to create a partial function. The function of functools.partial is to fix some parameters of a function (that is, set default values), and return a new function, which will be easier to call.
        When creating a partial function, you can actually receive three parameters: function object, *args and **kw.
        Such as: import functools
            int2 = functools.partial(int, base = 2)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324464330&siteId=291194637