Hello, I’m Brother Nongfei, thank you for reading this article, welcome one key three.


This article introduces you to the advanced aspects of Python functions, focusing on the mechanism of passing function arguments and functional programming.


Full of dry goods, suggested collection, need to see often. If you have any questions or needs, please feel free to leave a message.

preface

The last article introduced Python functions as well, but it was all about the basics. For those of you who haven’t read it yet, take a look at Python from Beginner to Mastering (11). . This article will focus on more in-depth aspects of function argument passing, lambda expressions, and functional programming. From entry to mastery, not always engage in some simple knowledge, but also to some hard goods. Dive deeper into the ocean of knowledge.

Python function argument passing mechanism

In the last article, we said that there are two mechanisms for passing arguments to Python functions: pass-by-value and pass-by-reference. So what’s the difference? What is the specific parameter passing mechanism? This chapter will answer both questions in the future. First, let’s look at value passing. The following code defines a swap function that takes two arguments, a and b. The job of this function is to swap in the values of a and b.

def swap(a, b): A, b = b, a print (= "" parameter a, a, b '=', and b) return a, a, b, b = 'yards farmers flying elder brother', 'come on' print (" arguments before calling a function a =", a, b = ', and b) swap (a, B) print(" a=", a, 'b=', b)

The running result is:

Parameter a= refueling b= refueling A = refueling b= refueling

You can see that the parameter was successfully changed without affecting the argument. Why is that? This is actually due toIn swap, the values of the parameters a and b are copies of the values of the arguments a and b, respectively. This means that after the call to swap, Python will take a copy of the parameters a and b that are given to swap. Changes to replicas will of course not affect the original values.The language description is empty, but let’s draw a picture: In Python, a method corresponds to a stack frame, and the stack is a last in, first out structure. The procedure described above can be represented by the following call diagram:



You can see that when you executeA, b = 'Nongfei Brother ',' Come on 'The code is that Python initializes the values of a and b in the main stack. When we call swap, we copy the a and b values of main to the swap stack. When swap swaps the values of a and b, it only affects copies of a and b, not a and b themselves.

But for list and dictionary data types,Since the data is stored in the heap and only the reference is stored in the stack, it changes when you modify the form parameter data.. Here is the code demo:

def swap(dw): # code below a, b two elements of the dw of value exchange of dw [' a '], dw [' b '] = dw [' b '], dw/' a 'print (" swap function, a = ", dw [' a'], "b =", dw [' b ']) dw = {' a ': 'Nongfei Brother ',' B ': } print(" a =", dw['a'], "b =", dw['b']) swap(dw) print(" a =", dw['b']) a =", dw['a'], " b =", dw['b'])

The running result is:

In the external DW dictionary before we call this function, a = b = fill in swap, a = b = fill in swap

It is clear that the value of the argument dw passed after the call to the function does change. This means that it is passed by reference. What is the difference between passing by reference and passing by value?



As you can see from the diagram above, the dictionary data is stored in the heap. In the main function’s stack, a reference is used to refer to the dictionary memory area. When we call swap, Python copies a reference to the dw to the parameter. When a dictionary is manipulated by a copy reference, of course, the dictionary’s data also changes.To sum up: passing by reference is essentially passing by value, except that the value is used to refer to the pointer itself, not the value to which the reference refers.To verify this we can modify the above code a little bit:

def swap(dw): Dw ['a'] = dw['b']; dw['a'] = dw['b']; dw['a'] = dw['b']; A = ", dw [' a '], "b =", dw dw = None [' b ']) print (" delete parameter to reference dictionary ", dw) dw = {' a ':' yards farmers flying elder brother ', 'b' : } print(" a =", dw['a'], "b =", dw['b']) swap(dw) print(" a =", dw['b']) a =", dw['a'], " b =", dw['b'])

The result of the run is:

A = B = A = B = A = B = A = B = A = A = B = A = B = A = B = A = B = A = B = A = B = A = B = A = B = A = B = A = B = A = B = A = B = A = B = A = B = A = B = C = A = B = C = A = C = A = B = C = A = B = C = C = A = C = B = C = C = C = C = C

After removing the reference to the dictionary from the parameter, the argument still gets the dictionary value. This is sufficient to say that the parameter is passed a copy of the reference to the argument.

Recursive function

Recursive functions are familiar to many of you. A recursive function is a function that calls itself inside a function. Recursive functions are often used to compute a sequence, traverse a province, traverse a folder, and so on. Note that a recursive function must be able to stop calling itself under certain conditions. Otherwise, you may end up in an endless loop of calls. For example, here is a sequence: f(0) = 1, f(1) = 4, f(n+ 2) = 2*f(n+ 1) +f(n), where n is an integer greater than 0, find the value of f(5). We can solve this problem using recursion. The following program will define a fn() function to calculate the value of f(5). According to f (n + 2) = 2 * f (n + 1) + f (n) formula can be derived f (n) = 2 * f (n – 1) + f (n – 2) formula.

def fn(n):
    if n == 0:
        return 1
    if n == 1:
        return 4
    return 2 * fn(n - 1) + fn(n - 2)
print(fn(5))

If n=5, the function returns 2*fn(4)+f(3). When n=4, the function returns 2*fn(3)+f(2). When n=3, the function returns 2*fn(2)+f(1). If n=2, it returns 2 times fn(1)+f(0) and if n=1, it returns 4 and if n=0, it returns 1. So, fn(2)=9,f(3)=22,f(4)=53,f(5)=128. His process recurses through the layers until he gets to the inner layer. And then you get back to the outer layer.

Variable scope

The scope of a variable -> is simply the scope of a variable. There are two kinds of variables in Python: local variables and global variables.

Variables defined inside a function are called local variables, and their scope is inside the function, as the function will live and die. Just like a front-line employee, your authority and responsibility are within your department (function), and you are not in charge of things that are outside your department.

The initialization process for local variables is that when the function executes, Python allocates a temporary storage space where all variables defined inside the function are stored. When the function completes, the temporary storage space is then freed and reclaimed. The variables stored in this space can no longer be used.



Just like the obj and name variables in the above code, they are used normally inside the function and prompted outside the functionNameError: name 'obj' is not defined.So it can be concluded that local variables cannot be used outside the function and form parameters are also local variables.

Variables that are defined outside of functions are called global variables and have scope throughout the application. That is, global variables can be used either outside or inside each function. Just as the boss can dictate to the entire company (the entire application), the smaller departments (functions) must obey him as well. Like the name variable in the code below, it can be used both inside and outside the function param_test1.

Param_test1 (obj): print('name=', name) print('name=', name) print('name=', name)

Gets a variable in the specified scope

  1. throughglobal()The Python function gets a global variable in a Python file, and the result is a dictionary.
  2. By calling inside a functionlocals()Functions can obtain local variables within the function. Give me an example!
def param_test1(obj): Print (' locals =', 'locals()) return obj + name param_test1(' locals ') name2 =' print(' globals() ')

The running result is:

Local variables have = {' name ':' zhang ', 'obj' : 'bill'} global variables have {' __name__ ':' __main__ ', '__doc__' : '@ date: 2021/7/19 21:23 \ n @ desc: \n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000226B627B208>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/python_demo_1/demo/function/param_test_fun.py', '__cached__': None, 'param_test1': < Param_test1 at 0x00000226B6221ea0 >, 'name2': 'name2'} < Param_test1 at 0x00000226B6221ea0, 'name2': 'name2'}

How do I use a global variable with the same name in a function

When a local variable inside a function has the same name as a global variable outside the function, the local variable will “shade” the global variable with the same name inside the function. Just as the so-called strong dragon does not suppress the head, in the function internal local variable is the head, the global variable this strong dragon’s limelight will be suppressed by it.

Print (name) print(name) print(name) print(name)

Running this function will report the following error:

Traceback (most recent call last):
  File "python_demo_1/demo/function/param_test_fun.py", line 33, in <module>
    test_1()
  File "/python_demo_1/demo/function/param_test_fun.py", line 31, in test_1
    print(name)
UnboundLocalError: local variable 'name' referenced before assignment

The error above tells us that when we execute print(name), the name is not defined because the name is defined on line 5. We expect to print the value of the global variable name on line 4, but since the function defines a local variable with the same name on line 5 (Python syntax dictates that assigning a value to a non-existent variable inside a function is the default to redefine a new local variable). The local variable name” shades “the global variable name. At the same time, the local variable name is initialized after print(name), which violates the principle of “define first, use later”, so the program will report an error.

How do you prevent a “shading” situation?

So how do you prevent global variables from being “Shadowed” by local variables with the same name inside a function? Here are two ways:

  1. If you want the program to still have access to the name global variable and you can redefine the name local variable in the function, you can do this by using the globals() function.
Print (' global name=', globals()['name']) test_1() print(' global name=', globals()['name']) test_1()

The running result is:

Local variable name= Li Sih Global variable name= Zhang San

Globals ()[‘name’] is used to access the global variable name directly, thus keeping the local variable name in the same place.

  1. Declare global variables within a function using the global keyword. To avoid assigning a global variable to a function (instead of redefining a local variable), you can use the global statement to declare a global variable.
Name = "def test_2" def test_2(): Print (' global name=', name) print(' global name=', name) print(' global name=', name) print(' global name=', name) globals()['name']) test_2()

The running result is:

Global variable name= local variable name= small wei wei global variable name= small wei wei

A local variable can also shade a global variable with the same name using the global keyword. After global is modified, the global variable is used until the local variable of the same name is defined.

Advanced usage of the function

Functions are assigned to other variables

Functions can not only be called directly, but functions can also be assigned directly to other variables. For example, if we define a function named my_fun below, we first assign the function name my_fun to the variable other, and then indirectly call my_fun() through other.

Def my_fun(): print(" other = my_fun ") : print(" other = my_fun ") : print(" other = my_fun ")

The result: my_fun is being executed

Passing functions as arguments to other functions

Python also supports passing functions as arguments to other functions, which means you can pass a function as a parameter. For example!

Def my_fun1(): return 'def my_fun2(name, my_fun1): return name + my_fun1 print(my_fun2(' ', my_fun1())))

The result of the operation is that you can do it. The above code first defines a function my_fun1 and then passes the function my_fun1 as an argument to my_fun2. The code works just fine.

Local functions (internal functions) and usage

Python supports not only defining local variables inside functions, but also defining functions inside functions. Such functions are called local functions. Give me an example!

Def outer_fun(): def inner_fun(): Print (' inner_fun ') return inner_fun = outer_fun() new_inner_fun()

The above code first defines the global function outer_fun, and then defines a local function inside that function, inner_fun. The local function is then returned. With the knowledge that functions can be assigned to variables, you can call the local function inner_fun without incident. Note that the problem of “masking” can also occur in local functions that define variables with the same name as the variables in the same function. The way to avoid this problem is not to use the global keyword, but to use the nonlocal keyword. Just like the following!

# def outer_fun(): name = 'def inner_fun()' : Print (' global name=', name) print(' global name=', name) print(' global name=', name) print(' global name=', name) New_inner_fun = outer_fun() new_inner_fun() return inner_fun()

The running result is:

Call local function global variable name= code nongfeige local variable name= small wei wei

Lambda expressions

Lambda expressions are supported in Python. Lambda expressions, also known as anonymous functions, are often used to denote functions that have an internal 1-line expression. The grammatical structure is:

Name =lambda [list]: expression

Where, to define a lambda expression, lambda keyword must be used; [list] is an optional parameter, which is equivalent to defining the function as a specified parameter list; Name is the name of the expression. For example, let’s say we have the following add function with an input of x, y. It comes back x plus y.

def add(x, y):
    return x + y

This function can be rewritten as a lambda expression, which results in lambda x,y:x+y. It is then assigned to an add variable. It looks like this.

add = lambda x, y: x + y
print(add(2, 3))

Lambda expressions, of course, are much more than that, and when combined with functional programming, as we’ll see later, they have a different effect. Next, let’s look at functional programming.

Functional programming

For normal functions, when the argument is a list or dictionary, the argument changes when the parameter is changed. Like this:

test_list = [1, 2, 3, 4] def second_multi(test_list): for i in range(len(test_list)): test_list[i] = test_list[i] * 2 return test_list for i in range(3): Print ('.format(STR (I)), second_multi(test_list))

The running result is:

The result of run 0 is: [2, 4, 6, 8] The result of run 1 is: [4, 8, 12, 16] The result of run 2 is:

You can see that each time you pass in the same parameter test_list, the result will be different three times. This is due to a change to test_list inside the function. The only way to avoid this is to redefine a new list inside the function, new_list. The function only modifies new_list.

test_list = [1, 2, 3, 4] def second_multi(test_list): new_list = [] for i in range(len(test_list)): new_list.append(test_list[i] * 2) return new_list for i in range(3): Print ('.format(STR (I)), second_multi(test_list))

The running result is:

The result of run 0 is: [2, 4, 6, 8] The result of run 1 is: [2, 4, 6, 8]

But now with functional programming, you can use functional programming to achieve the effect of the above code. Functional programming means that every piece of code is immutable and is made up of pure functions. The pure function here means that the functions themselves are independent of each other, so for the same input, there will always be the same output. What would happen if the above functions were transformed into functional programming? The above function is equivalent to the following functional programming map(lambda x: x * 2, test_list)

Test_list = [1, 2, 3, 4] for I in range(3): print('.format(STR (I)), list(map(lambda x: x * 2, test_list))

The running result is:

The result of run 0 is: [2, 4, 6, 8] The result of run 1 is: [2, 4, 6, 8]

As you can see from the above results, functional programming always has the same output for the same input. Python has the following three functions for functional programming.

The map () function

The map() function calls the specified function for each element in an iterable object and returns a map object. However, this map object cannot be output directly. It can be represented through a for loop or a list() function. The syntax of the map() function is map(function,iterable), where the function argument is passed a function, which can be a built-in function, a custom function, or a lambda anonymous function, and iterable is one or more iterable objects, which can be a list, a string, etc. Like this:

test_list1 = [1, 3, 5]
test_list2 = [2, 4, 6]
new_map = map(lambda x, y: x + y, test_list1, test_list2)
print(list(new_map))

The result: [3, 7, 11] The code above sums each element of the two lists to get a new list. That corresponds to the following function

def add(test_list1, test_list2):
    new_list = []
    for index in range(len(test_list1)):
        new_list.append(test_list1[index] + test_list2[index])
    return new_list
print(add(test_list1, test_list2))

The result is[3, 7, 11]

The filter () function

The filter() function returns either True or False for each element in iterable, and then forms a new traversable collection filter object from each element that returns True. Again, the filter object cannot be output directly. It can be represented through a for loop or a list() function. The syntax format of the filter function is: filter(function,iterable), where the function parameter indicates that a function is to be passed, which can be a built-in function, a custom function, or a lambda function; Iterable refers to one or more iterable objects, which can be lists, strings, etc. The next step is to filter out all the even numbers in the list.

test_list3 = [1, 2, 3, 4, 5]
new_filter = filter(lambda x: x % 2 == 0, test_list3)
print(list(new_filter))

The running result is: [2, 4]

To reduce () function

The reduce() function is typically used to do some accumulation on a collection. The grammatical structure is:

import functools
functools.reduce(function, iterable)

The function parameter represents a function to be passed in, which can be a built-in function, a custom function, or a lambda function. Iterable refers to one or more iterable objects, which can be lists, strings, etc.

import functools
test_list4 = [1, 2, 3, 4, 5]
product = functools.reduce(lambda x, y: x + y, test_list4)
print(product)

The running result is:15.

conclusion

This article details some of the most common advanced aspects of Python functions, including the mechanism of passing parameters to functions, the scope of variables, lambda expressions, and functional programming. These are some of the practical development of helpful knowledge points. Hope to the reader friends have some help, also welcome everyone a three even.

I am Brother Nongfei. Thank you again for reading this article.


The whole network of the same name [code farm fly elder brother]. Enjoy the joy of sharing every single step, every single mile


I am Brother Nongfei. Thank you again for reading this article.