Chapter 4: Functions

Posted by Castle on Tue, 06 Aug 2019 10:44:09 +0200

Chapter 4: Functions

Related links:
Function Introduction and Definition Function of [Li Gang-21 Days Pass Python-15]
Multiple Return Value Functions and Recursive Functions of [Li Gang-21 Days Pass Python-16]
Keyword parameters and default values of Python-17 [Li Gang-21 Days Customs Clearance]
Parameter Collection and Reverse Parameter Collection of [Li Gang-21 Days Pass Python-18]
Variable Scope of [Li Gang-21 Days Pass Python-19]
Local Function of Python-20 [Li Gang-21 Days Customs Clearance]
The Practice of Python-21: Define the Function of Calculating the Factor of N
The Practice of Python-22 [Li Gang-21 Days Customs Clearance]: Define the Function of Calculating Matrix Transposition

Chapter 4: Functions

Introduction to Functions and Definition of Functions

Definition of Function

  • The so-called function is to name a piece of code that implements a specific function and then execute (call) the code by that name.

The Law of Definition of Function

  • Functions require several key and dynamic data, which should be defined as the parameters of a function.
  • Functions need to pass out several important data that should be defined as return values
  • Internal Implementation of Functions

3. Functional Grammar

  • Functions must be defined before using them. The grammatical format is as follows:
'''
def function name (parameter list):
    # Functions consisting of zero to multiple executable statements
    ...... ...... 
    [return [return value]]
'''

[Example 1]

def first ():
    print("first function")
    for i in range(5):
        print(i)

first()  # first function 0 1 2 3 4

[Example 2]

def hello (name):
    print('hello function')
    print('Hello!' + name)

hello (python)  
# hello function
# Hello, python

[Example 3]

def max (a, b):
    r = a if a > b else b
    return r

x = max(3, 5)
print(x)  # 5
x = max(100, 0)
print(x)  # 100

IV. Documentation for functions

  • Just put the string after a function declaration and before the body of the function, and the string is the description document of the function.
  • Python built-in help() function to view help documentation for other functions
  • You can also view the description document of a function by its _doc_ attribute (double underscore)

(1) Use the help() function to view the built-in function document

(2) Use the _doc_ attribute to view the built-in function document

(3) Examples

def test (a):
    '''
    This is a simple function.
    A is a parameter
    '''
    pass

print(test.__doc__)
help(test)

Multiple Return Value Functions and Recursive Functions

I. Multiple Return Value Functions

  • Multiple return values are essentially tuples
  • Programs can either return tuples or multiple values directly (the system will automatically encapsulate them into tuples)
import random

def test ():
    # Generate three random uppercase characters
    c1 = chr(random.randint(65,90))
    c2 = chr(random.randint(65,90))
    c3 = chr(random.randint(65,90))
    return (c1, c2, c3)
    # return r1, r2, r3

2. Usage of Multiple Return Value Functions

  • When obtaining the return value of a function with multiple return values:
  • It can be obtained with a single variable (tuple).
  • Multiple variables are also available (tuple unpacking)

3. Recursive function

  • Calling it in the body of a function itself is called recursion of a function.
  • Function recursion contains an implicit loop that repeats a piece of code, but this repetition does not require loop control.
  • Note:
  • Recursion to known directions
  • Let recursion end without infinite recursion
# Calculating the factorial of n
def frac (n):
    if n < 1:
        print("n Not less than 1")
        return
    elif n == 1:
        return 1
    else:
        return frac(n - 1) * n 

print(frac(5))  # 120
print(frac(6))  # 720

Keyword parameters and default values of parameters

I. Keyword parameters

  • The parameter names of Python functions are not meaningless. Python allows parameter values to be passed in by name when calling functions.
  • When calling a function, there are two ways to specify values for parameters:
  • Location parameters: Each parameter must be assigned a parameter value in order
  • Keyword parameter (named parameter): specify parameter values by parameter name
def info (name, age, height):
    print("name: ", name)
    print("age: ", age)
    print("height: ", height)

# Location parameters
info('python', 18, 180)
# Keyword parameters
# Advantages: No need for sequencing, higher readability
info(age=18, name='python',height=180)
# Mixed use
# Note: Keyword parameters must be followed by location parameters
info('python', height=180, age=18)

2. Default values of parameters

  • Programs need to specify default values for one or more parameters when defining a function -- so that when calling a function, they can omit the input parameter values for the parameters and use the default values for the parameters directly.
  • The grammatical format for specifying default values for parameters is: parameter name = default value
def info (age, name='python'):
    print("name The parameters are:", name)
    print("age The parameters are:", age)

info(18)
# The parameter of name is: python
# The parameters of age are:18
info(20, 'java')
# The parameter of name is: java
# The parameters of age are:20
def say_hi(name='Sun WuKong', message='Hello, welcome to study. Python'):
    print("name: ", name)
    print("message: ", message)

say_hi()
# name: Monkey King
# message: Hello, welcome to Python
say_hi('White bone essence')
# name: white bone essence
# message: Hello, welcome to Python
say_hi(message='Welcome to the big family')
# name: Monkey King
# message: Welcome to the big family

Parameter Collection and Reverse Parameter Collection

I. Collection of General Parameters

  • Add an asterisk ("*") before the parameter, which means that the parameter can receive multiple parameter values, which are passed in as tuples.
  • The essence of parameter collection is a tuple: Python collects multiple values passed to the "*" parameter into a tuple
  • Python allows a variable number of parameters to be placed anywhere in the parameter list, but only with one parameter that supports normal parameter collection at most.
  • If the parameters that support normal parameter collection are in front, the latter parameters need to pass values using keyword parameters.
def test (num, *books):
    print("num: ", num)
    print("books: ", books)

test(3, 'python', 'java', 'cpp')
# num: 3
# books: ('python', 'java', 'cpp')
def info (*names, msg):
    for name in names:
        print("%s, %s" % (name, msg))

info('Sun WuKong', 'Zhu Bajie', 'The Devil of the Ox', msg='Welcome to all of you.')
# Monkey King, welcome
# Pig eight quit, welcome everybody.
# The Devil of the Ox, welcome to you all.

2. Keyword parameter collection

  • Two asterisks are added before the parameters, which support keyword parameter collection, and the collected parameters are treated as dict.
  • A function can support both normal parameter collection and keyword parameter collection
def test (num, *books, **scores):
    print("num: ", num)
    print("books: ",books)
    print("scores: ", scores)

test(5, 'python', 'java', 'cpp', Chinese=90, Mathematics=100)
# num: 5
# books: ('python', 'java', 'cpp')
# scores: {Language': 90,'Mathematics': 100}
def info (*names, msg, **scores):
    for name in names:
        print("%s, %s" % (name, msg))
    print(scores)

# dict parameter collection: only keyword parameters that cannot be explicitly passed in are collected
info('Sun WuKong', 'Zhu Bajie', 'The Devil of the Ox', msg='Welcome to all of you.', Chinese=90, Mathematics=100)
# Monkey King, welcome
# Pig eight quit, welcome everybody.
# The Devil of the Ox, welcome to you all.
# {Language': 90,'Mathematics': 100}

3. Reverse parameter collection

  • Reverse parameter collection: add "*" before tuples and lists and "**" before Dictionaries
  • Even for parameters that support collection, if a program needs to pass a tuple to that parameter, it also needs to use reverse collection.
def test (a, b):
    print(a)
    print(b)

vals = (20, 40)
msgs = ['aa', 'bb']
dicts = {'a': 80, 'b': 90}
# * Unpack tuples (reverse parameter collection)
test(*vals)
# 20
# 40
test(*msgs)
# aa
# bb
test(**dicts)
# 80
# 90

Variable scope

I. Scope of Variables

  • According to the location of the variable defined, there are two scopes of the variable:
  • Local variables: Variables defined in a function include parameters
  • Global variables: variables defined outside a function and globally
# global variable
a = 35

def info1 ():
    # local variable
    b = 'python'
    print(b)  # python
    print(a)  # 35

def info2 ():
    # local variable
    c = 'java'
    print(b)  # Error, local variables not accessible
    print(a)  # 35

2. Acquiring Dictionary of Variables

  • globals(): This function returns a dictionary of variables consisting of all variables in the global scope
  • locals(): This function returns a variable Dictionary of all variables in the current local scope
  • vars(object): Gets a dictionary of variables consisting of all variables within the scope of the specified object. If the object parameter is not passed in, vars() and locals() work exactly the same.

3. Variable masking

  • Global variables are accessible by default in all functions
  • If a variable with the same name as a global variable is defined in a function, then the case of local variable masking (hide) global variable will occur.
name = 'python'
def info ():
    # Still accessing the global variable name
    pirnt(global()['name'])  
    # Assignment of variables within a function, that is, defining a new name variable
    name = 'java'
    print(name)  

info()
# python
# java
print(name)  # python
name = 'python'
def info ():
    # Declare that name always uses global variables
    global name
    pirnt(name)  
    # Reassignment of global variable name
    name = 'java'
    print(name)  

info()
# python
# java
print(name)  # java

Local function

I. Local Functions

  • Functions defined in the body of a function become local functions
  • By default, local functions are hidden from the outside, and local functions can only be used within their closed functions.
def foo ():
    print('foo function')
    # Local function
    def bar ():
        for i in range(3):
            print('bar function')
    # Local functions are only valid in their closed functions
    bar()

foo()
# foo function
# bar function
# bar function
# bar function

2. Closed Function Returns Local Function

  • Closed functions can return local functions so that programs can use local functions in other scopes
  • If the closed function does not return the local function, then the local function can only be called within the closed function.
def foo ():
    print('foo function')
    # Local function
    def bar ():
        for i in range(3):
            print('bar function')
   # bar returns the function itself (the function is also a value of type function)
   # return bar() represents the execution result of the return bar function
   return bar

# The return value of the foo() function is the bar() function, so the variable r is used here to save the bar function.
r = foo()
r()
# foo function
# bar function
# bar function
# bar function
print(type(r))  # <class 'function'>

# The foo() function returns the bar function after it is called, and the bar function itself can also be called.
# 'foo()' = 'bar'  'foo()()' = 'bar()'
foo()()
# foo function
# bar function
# bar function
# bar function

3. Shadowing of Local Functions

  • Variables in a local function also obscure the local variables of its closed function.
  • Local functions can be declared by nonlocal in order to avoid masking local variables of closed functions.
def test ():
	name = 'python'
	def info ():
		print('info function')
		# Declare that the variable name is a local variable within the closed function that references it
		nonlocal name
		print('name: ', name)
		# Revaluation of Local Variables of Closed Functions
		name = 'java'
		print('name: ', name)
	info()
	print(name)

test()
# name: python
# name: java
# java

Practice: Define a function for calculating the factorial of N

Method 1: Use cycle

  • Control cycle counter from 1 to N
  • Let the loop counter multiply the previous result, knowing that the loop counter equals N
def fract (n):
	r = 1
	if n < 1:
		print("n Not less than 1")
		return
	else:
		for i in range(1, n+1):
			r *= i
		return r

print(fract(5))  # 120
print(fract(6))  # 720

Method 2: Recursion

  • The factorial of N equals the factorial of N times N-1.
  • When N is 1, the factorial of N is 1, which guarantees that recursion has an end point.
def fract (n):
	if n < 1:
		print("n Not less than 1")
		return
	elif n == 1:
		return 1
	else:
		# Recursion: Calling the function itself in a function
		return fract(n) = fract(n-1) * n

print(fract(5))  # 120
print(fract(6))  # 720

Method 3: Use reduce function

  • Python provides the reduce() function in the functools module, which uses the specified function to accumulate sequence objects
  • Usage of this function: reduce(function, sequence[, initial])
import functools

def fn (x, y):
	return x * y
	
def fract (n):
	if n < 1:
		print("n Not less than 1")
		return
	else:
		return functools.reduce(fn, range(1, n+1))
		# Another representation of fn functions: lambda x, y: x * y

print(fract(5))  # 120
print(fract(6))  # 720

Practice: Define a function to compute matrix transposition

Method 1: Nested cyclic transposition

  • First, create a new list with the same length as the first element of the original matrix.
  • Each element of the original matrix is traversed (each element is a list), and then each element is traversed by nested loops, adding the elements in the list to the list elements corresponding to the new list.
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

def print_matrix (m):
	for ele in m:
		for e in ele:
			print("%2d" % e, end=' ')
		print('')
		
def transform_matrix (m):
	# m[0] Several elements represent several columns of the original matrix
	rt = [[] for i in m[0]]
	for ele in m:
		for i in range(len(ele)):
			# rt[i] represents the first row of the new matrix
			# ele[i] represents the first column of the current row of the original matrix
			rt[i].append(ele[i])
	return rt

print_matrix(matrix)
'''
 1   2   3   4
 5   6   7   8
 9  10  11  12
13  14  15  16
'''

print_matrix(transform_matrix(matrix))
'''
 1   5   9
 2   6  10
 3   7  11
 4   8  12
'''

Method 2: Using zip function transposition

  • The purpose of the zip function is to merge multiple sequences: the first element of multiple sequences is merged into the first element, the second element of multiple sequences is merged into the second element,...
  • Using Reverse Parameter Collection
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

def print_matrix (m):
	for ele in m:
		for e in ele:
			print("%2d" % e, end=' ')
		print('')
		
def transform_matrix (m):
	# zip([1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]) -> (1, 5, 9), ......
	# Reverse parameter collection, which converts multiple lists in the matrix into multiple parameters and passes them to zip
	return list(zip(*m))

print_matrix(matrix)
'''
 1   2   3   4
 5   6   7   8
 9  10  11  12
13  14  15  16
'''

print_matrix(transform_matrix(matrix))
'''
 1   5   9
 2   6  10
 3   7  11
 4   8  12
'''

Method 3: Using numpy module transposition

  • Numpy module provides transpose() function to perform transpose, and the function return value is numpy's built-in type: array:
  • Calling the array's tolist() method converts the array into a list list list
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

def print_matrix (m):
	for ele in m:
		for e in ele:
			print("%2d" % e, end=' ')
		print('')
		
def transform_matrix (m):
	import numpy
	return tolist(numpy.transpose(m))

print_matrix(matrix)
'''
 1   2   3   4
 5   6   7   8
 9  10  11  12
13  14  15  16
'''

print_matrix(transform_matrix(matrix))
'''
 1   5   9
 2   6  10
 3   7  11
 4   8  12
'''

Topics: Python Java less Attribute