Python-study notes: advanced functions

Python tutorial-Liao Xuefeng's official website

Variables and functions

Variables can point to functions:

abs # 这个变量其实是 abs()
print(type(abs))

<class ‘builtin_function_or_method’>

Thus, the function name can be passed as a parameter , such as the definition of a function computed(x, y, f), such that x, yas the parameter to call fa function of the variable points.

  • The function object has an __name__attribute, you can get the name of the function
def computed(x, y, f):
    return f(x) + f(y)

print(computed(-2, -8, abs)) # 计算-2、-8的绝对值之和

10

For example computed()such a function that takes a variable function, called higher-order functions.

Higher order function

map() Higher order function

A function is created to associate with all elements of an iterable object and returned as an Iterator( iterator ), waiting to be executed.

  • This function is not executed at this time, and the function is executed only when the iterator is iterated.
result = map(abs, [-1, -2, 3]) # 得到 <class 'map'> 对象
print(list(result)) # 转为列表

[1, 2, 3]

  • resultIt is an inert objects , using list()calculated values and converted all of the list.

reduce() Higher order function

It applies a function to all elements of an iterable object. This function needs to receive two parameters , and reduce()will execute like this: take the result obtained by executing the two elements, and substitute the next element as a parameter to continue execution. Get the result and continue to substitute the next element for execution until the end.

  • The function has been executed at this point.

For example, combine a sequence to form a number:

from functools import reduce # 需要导入模块
def fn(x, y):
    return x *  10  + y

r = reduce(fn, [1, 2, 3])
print(r)

123

map()And reduce()usage examples: the string into digital

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(lambda x, y: x * 10 + y, map(char2num, s))

filter() Higher order function

And map()similar, but filter()is a function to create a link used to filter elements, according to the boolean value returned by the function to choose whether to retain elements. Return an iterator object.

  • Return a lazy object, not executed
# 判断一个数字反过来还是不是它
def is_palindrome(n):
    temp = n
    m =  0
    while temp >  0: # 有大于十位数的位数存在
        m = m *  10  + temp %  10  # 取个位数;下一次循环时,将个位数升级,
        temp = temp //  10  # 得到个位数以上的数字
    return n == m

print(list(filter(is_palindrome, range(1, 100)))) # 打印1~99的回数

sorted() Higher order function

sorted(lista)To sort a list, you can also pass in keyword parameters key. It is a function that can sort the list of elements after the function is applied .

  • For example sorted(lista, key=abs), sort the list by absolute value
  • Python uses the elements abs(), and then obtains the absolute value, internal proceed according to the original order, but when this sort of element, to see is the use of abs()the element after.
  • This function must return a value for Python to sort.

The original sorting of the string list is based on ASCII code:

>>> sorted(['bob', 'about', 'Zoo', 'Credit'])
['Credit', 'Zoo', 'about', 'bob']

Use keyparameters, making it ignore case when ordering:

>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)
# 排序看的是:'bob', 'about', 'zoo', 'credit'
['about', 'bob', 'Credit', 'Zoo']

In reverse order, you can pass in the third parameter reverse=True:

>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
['Zoo', 'Credit', 'bob', 'about']
  • Therefore, we can write a function to pass in, such as sorting a list of tuples:
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_name(t):
    return t[0] # 返回名字,让 Python 内部根据名字排序

L2 = sorted(L, key=by_name)
# 按照 'Bob', 'Adam', 'Bart', 'Lisa' 进行排序
print(L2)

Return function

Higher-order functions can receive functions as variables or return functions as return values.

def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum

f = lazy_sum(1, 3, 5, 7, 9)
# 它是:<function lazy_sum.<locals>.sum at 0x101c6ed90>,是一个函数
f() # 执行函数
  • Here sum()function can access the outside args, and when the lazy_sumreturn function sum, the parameters and variables are stored in the function returned , this is called "closure (the Closure)" program structure has great power.
  • Each call lazy_sum()returns a new function, even if the same argument to them is not ==the (not to say that operating results ranging, saying ranging function)
  • Internal function sum()variable function of the external reference variable called free
    • The free variables referenced in the closure are only related to the specific closure, and the free variables referenced by each instance of the closure do not interfere with each other.
    • Modifications of a closure instance to its free variables will be passed on to the next invocation of the closure instance.
  • Closure trap:
def my_func(*args):
    fs = []
    for i in range(03):
        def func():
            return i * i
        fs.append(func)
    return fs

fs1, fs2, fs3 = my_func()
print fs1()
print fs2()
print fs3()

The result of the program is not the result 0, 1, 4 we imagined. The actual result is all 4.
Because not returnreturn function , ijust outside a function of a common variable (not a function of the free variables closure), before returning function ihas been assigned to a 2, and returnafter iit became a free variables. It is already 2 at this time.

  • Note : Do not refer to any function that returns the loop variable , or follow-up will change the variables (in the returnfront).
def count():
    def f(j):
        def g():
            return j*j
        return g
    fs = []
    for i in range(1, 4):
        fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
    return fs

Closure example:

# 返回一个计数器函数,每次调用它返回递增整数,多个计数器函数之间互不干扰
def createCounter():
    n = 0
    def counter():
        nonlocal n
        n += 1
        return n
    return counter
  • In other words, a closure is to return a function, which independently owns the variable instance of the external function. (Similar to a small object)

Decorator

In the code running phase, dynamically add functions to an existing function. This function can be selected by many functions. (Java decorator mode)

  • It is essentially a higher-order function that returns a function.

In the object-oriented (OOP) design pattern, decorator is called the decoration pattern. The decoration mode of OOP needs to be implemented through inheritance and combination. In addition to the decorator that supports OOP, Python directly supports decorators from the syntax level. The decorator of Python can be implemented with functions or classes.

That now()function adds print log function log()as an example:

  1. Add before the original function @log:
@log
def now():
    print("2020-11-23")

This syntax is equivalent to:now = log(now)

  • The primitive becomes execution decorator function , is a function of the variable replacement , subsequent decorator function to return a function.
  1. In now()function of the above write functions defined decorator:
def log(func): # func 为 now 函数!
    def wrapper(*args, **kw): # *args, **kw 接收任意类型的参数
        print(f'call {func.__name__}():')
        return func(*args, **kw)
    return wrapper

The decorator function is to return a function, so you need to define a function to return internally.
Print log before calling: complete the function we need to add in this internal function, and then call the original function when returning func.


If the decorator function needs to pass in parameters, it needs to nest a higher-order function that returns a decorator (other names can also be used):

# 装饰器函数
def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print(f'{text} {func.__name__}():')
            return func(*args, **kw)
        return wrapper
    return decorator

# 原函数
@log('execute')
def now():
    print('2020-11-23')

Important : To understand @log('execute')the equivalent of:

now = log('execute')(now)
  • First execution log('execute'), execution log()returns decorator()a function, then arguments (now)call decorator()returns wrapper()a function.
  • Intuitively, the two parentheses execute two functions from outside to inside.

After completion of decorative function, because we are through @into the syntax of this function to be performed our decorator function, and then call the original function in our decorator function in, now = log(now)has been assigned, __name__it becomes wrapper:

  • Functionally, the requirements have been met, but some code executions that rely on function signatures will fail.
  • import functoolsIn the definition of wrapper()the add:@functools.wraps(func)
  • This code is equivalent to running:, wrapper.__name__ = func.__name__so it's perfect

Partial function

In the local area, set the default value for the function.
int(x, base=10): The string to a number, by basemodifying the digital band can.
For example, we need to turn a lot of binary digits, each time setting baseis very inconvenient:

import functools
# 创建函数变量int2,赋值为:【默认的参数base设置为2】的int函数 
int2 = functools.partial(int, base=2)
print(int2('1000000')) #输出: 64
  • The parameters here: the first one is the function to be set, and the latter will be substituted as the parameters of the function (follow the rules of ordinary calling functions)
    • If no keyword parameter is used, then it is a positional parameter

partial British [ˈpɑːʃl] American [ˈpɑːrʃl] adj. partial; partial; unfair

Guess you like

Origin blog.csdn.net/zsq8187/article/details/110003643