Python basic-11 function

11. Functions

                    . In Python, functions are usually divided into regular functions, anonymous functions and higher-order functions.

11.1 general functions

   define a function in Python using the def keyword in the following format:

def functionName(para1,para2,...,paran)
   """docString"""
   doSomething
   # comment
   return result

If a function in Python does not explicitly declare a return value, the default return value is None

   functions in Python are very flexible, which can be called simply or passed in very complex parameters from simple to complex parameter shapes as follows:

  • 1. Position parameter: transfer parameters in the specified order
  • 2. Default parameter: if the parameter has no transfer value, the default value when it is defined will be used
  • 3. Variable parameter: that is, the number of parameters passed is uncertain, and its definition format is * args
  • 4. Key parameter: that is to say, the passed parameter is the key value pair form, and its definition format is * * kwargs
  • 5. Name keyword parameter: the name used to restrict the keyword parameter. When calling, the keyword name must use the parameter name defined by the function
  • 6. Parameter combination: combination of various parameter types

11.1.1 location parameters

An example of the   position parameter is as follows:

  • def: keyword to declare a function
  • function_name: function name
  • arg: location parameter
  • Docstring: function description information, which is generally used to describe the function of the function, the meaning of the parameters passed and the description of the returned value. If docstring is written in the function, you can use help (function name) to view it
  • statement: the main body of the function, indicating the main code function

The    example code is as follows:

# Function definition
def func(name,age):
    print(f"name is {name} , age is {age}")
# Function transfer parameters
func("Surpass",28)

In position parameters, parameters are passed in the corresponding order. When calling a function, the number of parameters passed must be consistent with the number of parameters defined by the function

11.1.2 default parameters

   the number of parameters passed in the position parameter must be the same as the number of parameters defined by the function, otherwise an error will be reported. Is there any way to call a function that does not want to pass all the parameters, but wants the parameters not passed to use a fixed value? How to operate? The default parameter for this operation is as follows:

  • arg2=v: parameter name = default value, call the parameter, if no value is passed to it, use the default value, if there is a passed value, use the passed value
# Function definition
def func(name,age=25):
    print(f"name is {name} , age is {age}")
# Function transfer parameters
func("Surpass")

   in the above example, if age does not pass a value, the age value in the function is 25; if the value passed is 28, the age is 28

The parameter using the default parameter must be placed after the position parameter, otherwise an error will be reported

   when multiple default parameters can be used in a function, another situation will occur. There are too many parameters passed to remember the order. At this time, the parameters passed will lose their corresponding meaning. In this case, the value can be passed in the form of parameter name = parameter value. As follows:

# Function definition
def func(name,age=25,weight=55,city="shanghai"):
    print(f"name is {name} , age is {age},weight is {weight},now in {city}")
# Function transfer parameters
func("Surpass",city="wuhan",weight=60,age=28)

11.1.3 variable parameters

   if the number of parameters passed is fixed, position parameters or default parameters can be used, but what if the number of parameters passed is uncertain? Variable parameter function is provided in Python, which is usually represented by * args. The schematic diagram is as follows:

  • *args - variable parameter, can be from zero to any one, automatically assembled into a meta group

The    example code is as follows:

# Function definition
def func(name,age=25,weight=55,city="shanghai",*loveSport):
    print(f"name is {name} , age is {age},weight is {weight},now in {city},love sport is {loveSport}")
# Function transfer parameters
func("Surpass",28,60,"wuhai","run","tabletennis","basketball")

The output is as follows:

name is Surpass , age is 28,weight is 60,now in wuhai,love sport is ('run', 'tabletennis', 'basketball')

                        

# Function definition
def func(name,age=25,weight=55,city="shanghai",*loveSport):
    print(f"name is {name} , age is {age},weight is {weight},now in {city},love sport is {loveSport}")
# Function transfer parameters
func("Surpass",28,60,"wuhai",*("run","tabletennis","basketball"))

When using variable parameters, if there is a default parameter that needs to pass values, you cannot use parameter name = parameter value to pass values at this time. You need to pass values in the form of positional parameters, otherwise they will be passed as keywords

11.1.4 key parameters

                         

  • **kw - keyword parameter, which can be from zero to any one, automatically assembled into a dictionary.

   the difference between variable parameters and key parameters is as follows:

  • Variable parameter and key parameter can pass zero to any parameter
  • Variable parameters encapsulate the passed parameters into meta groups
  • Key parameters encapsulate the passed parameters into a dictionary
# Function definition
def func(name,age=25,weight=55,city="shanghai",*loveSport,**kwargs):
    print(f"name is {name} , age is {age},weight is {weight},now in {city},love sport is {loveSport},kwargs is {kwargs}")
# Function transfer parameters
func("Surpass",28,60,"wuhai",*("run","tabletennis","basketball"),otherinfoA="otherinfoA",otherinfoB="otherinfoB")

The output is as follows:

name is Surpass , age is 28,weight is 60,now in wuhai,love sport is ('run', 'tabletennis', 'basketball'),kwargs is {'otherinfoA': 'otherinfoA', 'otherinfoB': 'otherinfoB'}

   in addition to directly passing multiple key parameters, you can also encapsulate all parameters into a dictionary first, and then add * * before passing parameters (used for unpacking and disassembling dictionaries)

11.1.5 named key parameters

   for keyword parameter, the caller of function can pass in any unrestricted keyword parameter and its corresponding value. If you want to restrict the name of keyword parameter, you need to use named keyword parameter, such as only accepting city and job as keywords. It is defined as follows:

                  

  • **1. The separator required for naming key parameters is ***
  • 2. The parameter of named key must be passed in the parameter name, otherwise an error will be reported
  • **3. If a variable parameter already exists in the function definition, the following named key parameter does not need a separator ***
  • 4. Named key parameters can also define default values to simplify calling
  • 5. The separator * must be used to distinguish the location parameter and the named key parameter, otherwise it will be regarded as the location parameter

1. Define named key parameters

                     

def person(name,age,*,height,weight):
    print(f"name is {name},age is {age} , height is {height} , weight is {weight}")

person("Surpass",28,height=190,weight=69)

The output result is:

name is Surpass,age is 28 , height is 190 , weight is 69

**2. With variable parameters, the separator is no longer required for named key parameters ***

def person(name,age,*args,height,weight):
    print(f"name is {name},age is {age} , args is {args},height is {height} , weight is {weight}")

person("Surpass",28,1,2,height=190,weight=69)

The output result is:

name is Surpass,age is 28 , args is (1, 2),height is 190 , weight is 69

3. Named key parameter can be set with default value to simplify calling

def person(name,age,*args,height=189,weight):
    print(f"name is {name},age is {age} , args is {args},height is {height} , weight is {weight}")

person("Surpass",28,1,2,weight=69)

The output result is:

name is Surpass,age is 28 , args is (1, 2),height is 189 , weight is 69

4. If the named key parameter is missing the separator *, it will be considered as a position parameter

def person(name,age,height,weight):
    print(f"name is {name},age is {age} ,height is {height} , weight is {weight}")

person("Surpass",28,height=189,weight=100)

The output result is:

name is Surpass,age is 28 ,height is 189 , weight is 100

5. Combination of named key parameters and key parameters

def person(name,age,*,height,weight,**kwargs):
    print(f"name is {name},age is {age} ,height is {height} , weight is {weight},kwargs is {kwargs}")

person("Surpass",28,height=189,weight=100,keyA="keyA",keyB="keyB")

The output result is:

name is Surpass,age is 28 ,height is 189 , weight is 100,kwargs is {'keyA': 'keyA', 'keyB': 'keyB'}

6. Combination with other parameter types

def person(name,age,job="enginerr",*args,height,weight,**kwargs):
    print(f"name is {name},age is {age} occupation is {job},args is {args} height is {height} , weight is {weight},kwargs is {kwargs}")

person("Surpass",28,"IT",1,2,3,height=189,weight=100,keyA="keyA",keyB="keyB")

The output result is:

name is Surpass,age is 28 occupation is IT,args is (1, 2, 3) height is 189 , weight is 100,kwargs is {'keyA': 'keyA', 'keyB': 'keyB'}

11.1.6 parameter combination

   to define a function in Python, you can use position parameters, default parameters, variable parameters, keyword parameters and named keyword parameters. Although these parameters can be combined, you must follow certain rules. The order of parameter definitions is as follows:

  • Location parameter, default parameter, variable parameter, key parameter (most common)
  • Location parameter, default parameter, variable parameter, named key parameter
  • Location parameter, default parameter, named key parameter, key parameter
  • Location parameter, default parameter, variable parameter, named key parameter, key parameter

   syntax for variable and key parameters:

  • *args: variable parameter, which will be encapsulated into a meta group after receiving
  • **kwargs: keyword parameter, which will be encapsulated as a dictionary after receiving

In Python, although various parameters can be combined, it is not recommended to use too many combinations, otherwise the function is difficult to understand.

11.2 anonymous functions

                      . In some cases, the function implementation is very simple. If it needs to be defined every time, it will be very troublesome. In Python, lambda expressions are provided to simplify this operation. Functions defined by lambda are called anonymous functions (because there is no function name). Their expressions are as follows:

  • lambda: key to define anonymous function
  • argument_list: the parameters of the function are the same as those of the normal function
  • : colon, separator for anonymous function parameters and expressions
  • Expression: anonymous function expression, corresponding to function body code in general function

The    example code is as follows:

1. Example 1

f=lambda x,y:list(range(x,y))
print(f(0,10))

# It is equivalent to the following function functions
def f(x,y):
    print(list(range(x,y)))

The output result is:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

2. Example 2

f=lambda *args:print(sum(args))
f(1,2,3,4,5)

# It is equivalent to the following function functions
def f(*args):
    print(sum(args))

The output result is:

15

3. Example 3

f=lambda **kwargs:print(kwargs)
f(keyA="keyA",keyB="keyB",keyC="keyC")

# It is equivalent to the following function functions
def f(**kwargs):
    print(kwargs)

The output result is:

{'keyA': 'keyA', 'keyB': 'keyB', 'keyC': 'keyC'}

Although anonymous functions are easy to use, they need not be overused in combination with the actual situation. If a function needs to be called frequently, def needs to be defined as a regular function

11.3 higher order functions

   high order functions are very common in functional programming, and their main forms are as follows:

  • Argument is a function
  • Return value type is function

11.3.1 closure

Wiki explains as follows:

In computer science, Closure, also known as Lexical Closure or function closures, is a function that references a free variable. This referenced free variable will exist with this function, even if it has left the environment in which it was created. So, there is another way of saying that a Closure is an entity composed of a function and its associated reference environment. Closures can have multiple instances at runtime. Different reference environments and the same function combination can produce different instances.

The closure in    Python is a high-order function. The return value is a function object. Simply speaking, a function definition refers to a variable defined outside the function, and the function can be executed outside its definition environment. This function is called a closure. The example is as follows:

def outter(x):
    temp=[x]
    def add():
        temp[0]+=x
        print(temp)
    def sub():
        temp[0]-=x
        print(temp)
    return add,sub

add,sub=outter(100)
add()
sub()

The output is as follows:

[200]
[100]

Partial function

The main function of    partial function is to fix one or more parameters of the function, make it a new function, and use it in other applications. To use partial functions, you need to import the following packages, as follows:

from functools import partial

                   

tempList=[12,100,999,12412,1,-98,1209]
print(sorted(tempList))

   the above example code is to sort the list, and the default sorting is ascending sorting. If reverse sorting is required, the parameter reverse=True needs to be added separately, as shown below:

sorted(tempList,reverse=True)

   suppose you need to use this sort function multiple times, it's very troublesome to write this every time. Besides rewriting the function, is there any way to fix the reverse parameter of the function? Now it's time for the partial function to play, as shown in the following example:

mySortedpartial=partial(sorted, reverse=True)
print(mySortedpartial)

The output is as follows:

functools.partial(<built-in function sorted>, reverse=True)

    from the output result, mySortedpartial is a function, and the parameters set separately are fixed, so that you do not need to input this parameter each time, and the function function can still be used normally, as shown below:

from functools import partial

tempList=[12,100,999,12412,1,-98,1209]
print(sorted(tempList,reverse=True))

mySortedpartial=partial( sorted, reverse=True )
print(mySortedpartial(tempList))

The output is as follows:

[12412, 1209, 999, 100, 12, 1, -98]
[12412, 1209, 999, 100, 12, 1, -98]

                         

from functools import partial

def getUserInfo(username,age,sex,country):
    userInfo = []
    userInfo.append((username,sex,age,country))
    return userInfo


if __name__ == '__main__':
    myGetUserInfo=partial(getUserInfo,sex="male",country="China")
    print(myGetUserInfo)
    print(myGetUserInfo("Surpass",28))
    print(myGetUserInfo("Kevin",35))
    print(myGetUserInfo("Leo",38))

The output is as follows:

functools.partial(<function getUserInfo at 0x000001ACCA803048>, sex='male', country='China')
[('Surpass', 'male', 28, 'China')]
[('Kevin', 'male', 35, 'China')]
[('Leo', 'male', 38, 'China')]

   when the number of parameters of a function is large and the default value of the parameter does not meet your needs, you can use partial functions to create a new function to simplify the call.

In short, we can understand that in order to meet our own needs, after fixing the values of some parameters of the original function, creating a new function to simplify the call, is it very similar to taking an alias for a function?

11.3.3 Coriolis

Currierization refers to the process of changing the original function accepting two parameters into a function accepting one parameter, and the new function parameter returns a function taking the original second parameter as the parameter. That is, g=f(x,y) changes to g=f(x)(y)

   take the ordinary addition function as an example:

def addA(x:int,y:int)->int:
    return x+y

With function nesting, you can convert to the following forms:

def addB(x:int)->int:
    def subadd(y:int):
        return x+y
    return subadd

Comparing the above two functions, let's take a look at the call forms, as follows:

print(addA(1,2))
g=addB(1)
print(g(2))
print("Abbreviated form")
print(addB(1)(2)) #  Change g=f(x,y) to g=f(x)(y)

The output is as follows:

3
3
 Abbreviated form
3

11.4 function scope

Every time the system executes a function, a new local namespace is created. The namespace represents a local environment that contains the parameter name of the function and the variable name assigned in the function body. When these names are resolved, the interpreter searches the local namespace first; if no matching name is found, it searches the global namespace. The global namespace of a function is always the module that defines the function. If the interpreter cannot find a matching value in the global namespace, the built-in namespace will be checked finally. If not, the NameError exception will be triggered.

Search order of variables local namespace - > global namespace - > built in namespace

The    example code is as follows:

a=12
def f():
    a=120

if __name__ == '__main__':
    print(f"The value of the variable before calling the function{a}")
    f()
    print(f"After the function is called, the value of the variable{a}")

The output is as follows:

Before calling the function, the value of the variable 12
 After the function is called, the value of the variable 12

   in the above example code, although the value of variable a is modified in function f(), the value of return a does not change. When variables are assigned in a function, they are always bound to the local namespace of the function. Therefore, variable a in the function body refers to a new object with a value of 120, rather than the external variables. If you want to change this behavior, you can use the keyword global.

The global keyword can explicitly declare the variable name as belonging to the global namespace. It can only be used when the global variable needs to be modified. It can be placed anywhere in the function and can be reused.

a=12
b=13
def f():
    global a
    a=120
    b=130

if __name__ == '__main__':
    print(f"The value of the variable before calling the function{a} - {b}")
    f()
    print(f"After the function is called, the value of the variable{a} - {b}")

The output is as follows:

Before calling the function, the value of the variable 12 - 13
 After the function is called, the value of the variable 120 - 13

Let's take a look at the following example:

def counter(start):
    n=start
    # Defining nested functions
    def show():
        print(f"current value is {n}")
    while n >0:
        show()
        n-=1

In Python, functions can be nested. Variables in nested functions are defined by static scopes, that is, when the interpreter resolves names, it first checks the local scopes, and then checks the scopes defined by the external nested functions layer by layer. If no match is found, the global namespace and built-in namespace are searched, but the internal function cannot reassign the local variables defined by the external function. There is a problem in the following code:

def counter(start):
    n=start
    # Defining nested functions
    def show():
        print(f"current value is {n}")
    def decrement():
        n-=1 #Pycham will automatically check out the problem
    while n >0:
        show()
        decrement()

In this case, the keyword nonlocal can be used in Python 3 to solve the problem, as shown below:

def counter(start):
    n=start
    # Defining nested functions
    def show():
        print(f"current value is {n}")
    def decrement():
        nonlocal n # Bind to external n
        n-=1
    while n >0:
        show()
        decrement()

Address: https://www.cnblogs.com/surpassme/p/12975455.html
This article is synchronously published on wechat subscription number. If you like my article, you can also pay attention to my wechat subscription number: woaitest, or scan the following QR code to add attention:

Tags: Python Lambda Programming

Posted on Wed, 27 May 2020 08:52:39 -0400 by acroporas