Study Notes: Python3 functional programming

Access to personal use only, please correct me if wrong also.

It is a functional programming abstract computing programming model.

Functional programming features

1, calculated as a function rather than the command.

2, functions written in a purely functional programming language is not variable.

3, supports higher-order functions, concise code.

Python supports functional programming supports the following features

1, not a purely functional programming: allows variable.

2, supports higher-order functions : functions can also be passed as a variable

3, support for closures : With the closure will be able to return function.

4, limited support for anonymous functions .

  • Higher-order functions

    Direct definition: receiving function can function as arguments.

    He began to explain

    • Variables can point to functions

      It means the function itself can be assigned to a variable

      a = abs
      
      print(abs)  # output:<built-in function abs>
      print(a)    # output:<built-in function abs>

      Since the assignment is successful, is not it also can be called?

      a = abs
      
      print(a(-10))       # output:10

      objk, Explanatory variable anow points to the absfunction itself. Call a()functions and call abs()completely identical .

    • The function name is variable

      Generally it means that the function name is the variable to point to the function. absThis variable points to the absfunction.

      That is, if you abspoint to other functions , it abs()will not be the absolute value of the function.

      Examples

      abs = len               # 把abs这个变量指向len函数
      
      print(abs)              # 此时abs它就是一个len函数,<built-in function len>
      print(abs(10))          # 你想要去求绝对值,是会报错的。
      print(abs([1,2,3]))     # 而是需要你求长度。3前面两

    It should be said plainly a.

    Since variables can point to a function, a function that can receive another function as a parameter, which is the higher-order functions .

    Experience the most simple higher-order functions

    import math
    
    def sqrt_add(x, y, f):
        return f(x) + f(y)
    
    print(sqrt_add(25, 9, math.sqrt))
    # output:8.0
  • Python built-in four higher-order functions

    • map()

      This function, it receives a function and a iterable . mapThe function of the incoming sequence are sequentially applied to each element .

      And return the results as a new iterator. Yes, map it is an object returned iterator .

      To obtain specific data, by next()the method. It can also list()function.

      Examples

      def f(x):
          return x * x
      
      print(list(map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])))
      # output:[1, 4, 9, 16, 25, 36, 49, 64, 81]
      
      # 首字母大写,后续字母小写的规则
      def format_name(s):
          return s[0].upper() + s[1:].lower()
      
      print(list(map(format_name, ['adam', 'LISA', 'barT'])))
      # output:['Adam', 'Lisa', 'Bart']
    • reduce()

      This function receives parameters and map()the like.

      But the behavior and map()different reduce()incoming function f must receive two parameters, reduce()for listeach element called repeatedly

      With the function f, and returns the final result value.

      By summing quadrature to simplify its understanding. Of course, it can be directly summed with Python sum (), where in order to understand.

      from functools import reduce
      
      def f(x, y):
          return x + y
      
      print(reduce(f, [1, 3, 5, 7, 9]))
      # output:25
      # 还可以接收第三个参数,作为计算的初始值。
      print(reduce(faa, [1, 3, 5, 7, 9], 100))
      # output:125
      
      # 第二个例子,求积函数
      def prod(x, y):
          return x * y
      
      print(reduce(prod, [2, 4, 5, 7, 12]))
      # 3360
    • filter()

      This function receives parameters and map()the like. The role of this function f is determined for each element, returns Trueor False, if

      Is Trueit to retain that element.

      Yes, with the results returned map(), it is part of iterators.

      Examples

      # 从一个list [1, 4, 6, 7, 9, 12, 17]中删除偶数,保留奇数
      
      def is_odd(x):
          return x % 2 == 1
      
      print(list(filter(is_odd, [1, 4, 6, 7, 9, 12, 17])))
      # output:[1, 7, 9, 17]
      
      # 删除None或者空字符串
      def is_not_empty(s):
          return s and len(s.strip()) > 0
      
      print(list(filter(is_not_empty, ['test', None, '', 'str', '  ', 'END'])))
      # output:['test', 'str', 'END']

      Seen, filter()function returns a sequence from a qualified sieve element.

    • sorted()

      The core ranking algorithm is to compare the size of two numbers. If it is a string or a dictionary it? With the size of mathematics does not make sense, to be

      To compare by abstract functions.

      • Sort of list

        print(sorted([23, -454, 11, -6, 5]))
        
        # output:[-454, -6, 5, 11, 23]
      • Acceptable keyfunction to implement custom sorting.

        print(sorted([23, -454, 11, -6, 5], key=abs))
        
        # output:[5, -6, 11, 23, -454]
        # key指定的函数将作用于list的每一个元素上,并把返回的结果进行排序。
      • Sorting strings, in accordance with the size of the ASCII comparison.

        Now propose to ignore case, then sorted, we do not need the whole first string changed to lowercase.

        According to the previous example, simply by keyprocessing to the received function.

        print(sorted(["harden", "Durant", "jordan", "curry", "O'Neal"], key=str.lower))
        
        # output:['curry', 'Durant', 'harden', 'jordan', "O'Neal"]

        To sum up:sorted() the essence of the sort function is to implement a mapping function.

  • Return function

    • Function as a return value

      Directly example to analyze

      def f(x):
          print("run f_function ...")
          def g():
              print("run g_function ...")
              return x
          return g
      
      print(f(5))
      # output:
      run f_function ...
      <function f.<locals>.g at 0x0000017364A0BF28>
      # 当调用f函数时,返回的并不是x的值,而是g函数。
      
      # 要去调用g函数,才会返回x的值
      print(f(5)())
      # output:
      run f_function ...
      run g_function ...
      5 is ok

      In this example, the function fin turn defines a function g, and the function of internal greference an external function fparameters and local variables.

      When the ffunction returns g, the parameters and variables are stored in the function returned. This is called "closure" .

    • Closure

      Characteristics of the closure is returned by the function further reference to the outer function of local variables and parameters .

      Look simple, but it is still to use the difficult of.

      Now let you implement a function with closure, were calculated 1x1, 2x2,3x3

      def count():
          fs = []
          for i in range(1, 4):
              def f():
                   return i*i
              fs.append(f)
          return fs
      
      f1, f2, f3 = count()
      
      print(f1(), f2(), f3())

      Your desired outcome is 1,4,9. I hope so. The actual output is 9,9,9

      The reason is that when count()the function returns the three functions, the value of the variable three functions referenced i has become 3. When you go to call it is

      f1() -> return value is 9.

      Therefore, the function returns do not refer to any loop variables or variable subsequent changes occur .

      To correct the above function

      def count():
          fs = []
          for i in range(1, 4):
              def f(i):
                  return lambda : i*i
              fs.append(f(i))
          return fs
      f1, f2, f3 = count()
      
      print(f1(), f2(), f3())

      The original return i*ireplaced return lambda : i*i. Use lambdaan anonymous function.

      The reason is the same parameter binding function together with the value unchanged.

  • Anonymous function

    With map()function as an example, again calculated f(x)= x², before the method is to define a function.

    def f(x):
        return x * x
    
    print(list(map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])))

    Now the way is a direct write anonymous function

    print(list(map(lambda x: x*x, [1, 2, 3, 4, 5, 6, 7, 8, 9])))

    Obviously, lambda x: x * xthat function f().

    Keyword lambda represents the anonymous function, before the colon xrepresents a function parameter .

    Anonymous function has a limit, that is only one expression, do not write return, the return value is the result of the expression.

    Of course, anonymity is a function object, can be assigned to a variable, and then use a variable to call the function.

  • Decorator

    Without modifying the original function of the premise, the dynamic new features to it . Called "decorator."

    It returns a new function by higher-order functions

    def f1(x):
        return x * 2
    def new_fn(f):
        def fn(x):
            print("call " +  f.__name__ + " ()")
            return f(x)
    
        return fn
    
    g1 = new_fn(f1)
    print(g1(5))
    
    # 这种调用方式的结果:f1的原始定义函数被彻底隐藏了。
    f1 = new_fn(f1)
    print(f1(5))

    Python built-in @ syntax is to simplify decorator calls

    @new_fn == f1 = new_fn(f1)

    • No reference decorator

      From the previous description, we know the nature of Python decorator is a higher-order function that accepts a function as a parameter, then

      After the return to a new function.

      Introducing the ultimate combined function mentioned spiral.

      from functools import reduce
      
      def log(f):
          def fn(x):
              print 'call ' + f.__name__ + '()...'
              return f(x)
          return fn
      
      # 首先是factorial函数要去调用是可型的。因为只要一个参数。
      @log
      def factorial(n):
          return reduce(lambda x,y: x*y, range(1, n+1))
      print(factorial(10))
      
      # 那如果add函数也要去调用这个装饰器就会报错,因为有两个参数,不匹配。
      @log
      def add(x, y):
          return x + y
      print(add(1, 2))
      

      Let the @logadaptive function any parameters defined, can be used *argsand **kw, to ensure that any number of arguments always normal call.

      Amendment

      def log(f):
          def fn(*args, **kw):
              print('call ' + f.__name__ + '()...')
              return f(*args, **kw)
          return fn
    • Parameterized decorator

      Examples

      def log(prefix):
          def log_decorator(f):
              def wrapper(*args, **kw):
                  print('[%s] %s()...' % (prefix, f.__name__))
                  return f(*args, **kw)
              return wrapper
          return log_decorator
      
      @log('DEBUG')
      def test():
          pass
      print(test())

      This layer 3 is nested. You only need to understand the parameterized decorator usually takes three layer loop, you can go to write according to this template.

      Here's a simple talk about:

      @log('DEBUG')
      def test():
          pass
      
      # 这个定义相当于是    
      test = log('DEBUG')(test)
      # 再进行转换
      log_decorator = log("DEBUG")
      test = log_decorator(test)
      # 再进行转换就是
      log_decorator = log("DEBUG")
      @log_decorator
      def test():
          pass
      
      # 所以,带参数的log函数首先返回一个decorator函数,再让这个decorator函数接收test并返回新函数。

      Whether or not understood, reference is now going resolved with the decorative instance code execution flow.

      First execution log("DEBUG"), returns the log_decoratorfunction, then the function call returns, the parameters are testa function, return

      The final value is wrappera function.

    • Perfect decorator

      In fact, the above two methods basically get away, why perfect, because the original function plus a decorator, so the original letter

      The number of the function name becomes the function name of the new function. More than a as an example, testthe function name becomes wrapper.

      You can __name__.pyget to the function name. This means that the code-dependent function names will fail, such as

      test.__doc__And other attributes. The original function is required __name__to copy attributes to other wrapper()functions.

      Python For convenience, the need to write wrapper.__name__ = f.__name,

      wrapper.__doc__ = f.__doc__Such an operation. Like directly into the module.

      By functoolsthis tool to complete the replication process.

      import functools
      
      def log(f):
          @functools.wraps(f)
          def fn(*args, **kw):
              print('call ' + f.__name__ + '()...')
              return f(*args, **kw)
          return fn
      
      def log(prefix):
          def log_decorator(f):
              @functools.wraps(f)
              def wrapper(*args, **kw):
                  print('[%s] %s()...' % (prefix, f.__name__))
                  return f(*args, **kw)
              return wrapper
          return log_decorator

      These are modified decorator part. As can be seen further directed to a method of writing on the front function.

  • Partial function

    Mentioned a functoolsmodule that many functions, one of which is a partial function.

    The biasing function is to reduce the function call difficult.

    I mentioned in the chapter function, by setting the parameter default values ​​to reduce the difficulty of function calls.

    Inside the function mentioned int()functions, may be binary conversion. But the default is decimal.

    In order to avoid each call is int(x, base=2), we write a function. To customize.

    functools.partialCan be a function of many parameters become less of a new parameter function, fewer parameters need to specify the default when you create

    Value, so that the difficulty of the new function calls is reduced.

    import functools
    
    int2 = functools.partial(int, base=2)
    
    print(int2('1000000'))
    # output:64
    print(int2('1010101'))
    # output:85

    Finally, add this: When you create a partial function, can actually receiving function objects, *argsand **kwthese three parameters.

Guess you like

Origin www.cnblogs.com/lowkeyao/p/11300441.html