An interpretation of Python decorator

Copyright notice: This is the original article of Colin Cai, welcome to post. If you want to transfer, you must indicate the original website

  http://www.cnblogs.com/Colin-Cai/p/12977127.html 

Author: Windows

QQ / wechat: 6679072

  E-mail: 6679072@qq.com

In theory, function is the first class function language, which can use functional programming to make decorators by using operators (higher-order functions).

A decorator is usually an operator that takes a function as a parameter and returns another function. Decorator, as the name implies, is to "decorate" one function to get another function. Why decorate it? The purpose is to modify the function in design, for example, the output of the original function needs to be reprocessed, or the input parameters of the original function are not the same, or both, and so on.

 

Iteration is a common method in programming. Its calculation method is represented by continuous state transformation, and the state transformation is unique.

For example, we use Scheme to represent iteration.

;stat Represents the current state, next Represents the state change function, final?Indicates whether the status is terminated
(define (iterate-orgin stat next final?)
  (if (final? stat)
      stat
      (iterate-orgin (next stat) next final?)))

;take next Functions and final?Function to a function
(define (iterate stat f-stat)
  (iterate-orgin stat (f-stat 'next) (f-stat 'final)))

;The final iteration function we need
(define (it f-stat)
  (lambda (stat) (iterate stat f-stat)))

  

The operator it constructed above is the function used to "decorate" the iteration.

We construct an iteration to sum the list:

You can add the first two of the list at a time, such as summing (1 23 4 5), through the following states:

  (1 2 3 4 5)

  (3 3 4 5)

  (6 4 5)

  (10 5)

  (15)

  15

The final result is 15.

The code can be as follows:

(define (make-sum-func sym)
 (if (eq? sym 'next);next function
  (lambda (lst)
   (if (pair? lst)
    (if (null? (cdr lst))
     (car lst)
     (cons (+ (car lst) (cadr lst)) (cddr lst)))
    lst))
  (if (eq? sym 'final?);final?function
   (lambda (lst) (not (pair? lst)))
   '())))

 

Then test ((it make sum func) '(1 23 4 5)) to get the final result 15.

The above two functions are written together, and we can separate them again.

  

;Define a packaging function
(define (wrap-next-final next final?)
 (lambda (sym)
  (if (eq? sym 'next)
   next
   (if (eq? sym 'final?)
    final?
    '()))))

;below next and final?Two functions can be written separately
(define make-sum-next
 (lambda (lst)
  (if (pair? lst)
   (if (null? (cdr lst))
    (car lst)
    (cons (+ (car lst) (cadr lst)) (cddr lst)))
   lst)))

(define make-sum-final?
 (lambda (lst) (not (pair? lst))))

;So the function can be represented as follows
(define make-sum-func (wrap-next-final make-sum-next make-sum-final?))

 

In a word, decorators are such operators.

 

It's the same with Python, but Python provides @ syntax, which is actually a syntax sugar. It's more like a syntax reminder than shorthand. It's a decorator.

We want to show mysym this time, or sum.

First write a simple mysum function to sum:

def mysum(*args):
    ret = 0
    for i in args:
        ret += i
    return ret

 

Make an operator to expand its input parameters:

It needs to be used to judge whether an object is an iterative object,

  from collections import Iterable

Then, if you want to determine whether object x is an iterative object, you only need to:

  isinstance(x, Iterable)

The operators are as follows:

from collections import Iterable
def args_expan(f):
    def f2(*args):
        lst = []
        for i in args:
            if isinstance(i, Iterable):
                lst.append(f(*i))
            else:
                lst.append(i)
        return f(*lst)
    return f2

 

Then add the decorator logo before mysum

@args_expan
def mysum(*args):
    ret = 0
    for i in args:
        ret += i
    return ret

 

The tests are as follows:

print(mysum(1,2,3,4,5))
print(mysum((1,2,3,4,5)))
print(mysum([1,2,3,4,5]))
print(mysum(range(1,6)))
print(mysum(map(lambda x:x+1, range(5))))
print(mysum(filter(lambda x:x<6, range(10))))

#Construct a generator
def gen_range(a, b):
    while a < b:
        yield a
        a += 1

print(mysum(\
    filter(lambda x:x<6, range(10)), \
    6, \
    [7,8], \
    (9, 10), \
    map(lambda x:x+11, range(10)), \
    gen_range(21,101)))

 

Operation results in:

15
15
15
15
15
15
5050

Finally, we can see that the function function has been extended.

This decorator can also decorate other functions, such as product, statistics, etc.

 

Thus, the decorator is such an operator, which is generally used to modify the input or output of a function to avoid repeated code writing.

Keywords: Python Lambda Programming Windows

Added by William on Sun, 31 May 2020 10:45:35 +0300