# Chapter 6 function oriented programming

Posted by SiriusB on Mon, 02 Mar 2020 06:01:33 +0100 # Chapter VI functions

## 4.1 function definition and call

### 4.1.1 why to use function

1. Improve code reusability -- abstract and encapsulate as function

2. Decompose complex big problems into a series of small problems, divide and rule -- the idea of modular design

3. Facilitate code maintenance and management

Sequential form

```# Factorial 5
n = 5
res = 1
for i in range(1, n+1):
res *= i
print(res)

# Factorial 20
n = 20
res = 1
for i in range(1, n+1):
res *= i
print(res)
```
```120
2432902008176640000
```

Abstract into function

```def factoria(n):
res = 1
for i in range(1,n+1):
res *= i
return res

print(factoria(5))
print(factoria(20))
```
```120
2432902008176640000
```

### 4.1.2 function definition and call

White box: input processing output

Three elements: parameter, function body and return value

1, definition

def function name (parameter):

function body

return return value

```# Find the area of a square
def area_of_square(length_of_side):
square_area = pow(length_of_side, 2)
return square_area
```

2. Call

Function name (parameter)

```area = area_of_square(5)
area
```
```25
```

### 4.1.3 parameter transfer

0. Formal parameter and actual parameter

• Parameter (formal parameter): the parameter when the function is defined, which is actually the variable name

• Actual parameter (actual parameter): the parameter when the function is called, which is actually the value of the variable

1. Location parameters

• To assign (Associate) parameters in strict order of position

• Generally used when the parameters are relatively small

```def function(x, y, z):
print(x, y, z)

function(1, 2, 3)    # x = 1; y = 2; z = 3
```
```1 2 3
```
• The number of actual parameters and formal parameters must correspond one by one, one cannot be more, one cannot be less
```function(1, 2)
```
```---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-6-2a7da6ff9675> in <module>
----> 1 function(1, 2)

TypeError: function() missing 1 required positional argument: 'z'
```
```function(1, 2, 3, 4)
```
```---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-8-748d3d0335e6> in <module>
----> 1 function(1, 2, 3, 4)

TypeError: function() takes 3 positional arguments but 4 were given
```

2. Key parameters

• Break the position limit and call its name directly to pass the value (parameter = actual parameter)

• One by one correspondence must be observed in the number of actual participating parameters

• It is often used in the case of many parameters

```def function(x, y, z):
print(x, y, z)

function(y=1, z=2, x=3)    # x = 1; y = 2; z = 3
```
```3 1 2
```
• Location parameters can be mixed with key parameters

• However, the location parameter must precede the key parameter

```function(1, z=2, y=3)
```
```1 3 2
```
```function(1, 2, z=3)
```
```1 2 3
```
• Cannot pass value repeatedly for the same parameter
```def function(x, y, z):
print(x, y, z)

function(1, z=2, x=3)
```
```---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-12-f385272db011> in <module>
3
4
----> 5 function(1, z=2, x=3)

TypeError: function() got multiple values for argument 'x'
```

3. Default parameters

• Assign a value to a parameter in the definition phase -- the common value of the parameter

• Assign a value to a parameter in the definition phase -- the common value of the parameter

• Default parameters must be placed after non default parameters

• When calling a function, you can not pass a value to this parameter

• The method of class in machine learning library is very common

```def register(name, age, sex="male"):
print(name, age, sex)

register("Da Jie Zi", 18)
```
```18 male
```
• You can also pass values according to normal parameters
```register("Lin Chiling", 38, "female")
```
```Lin Zhiling 38 female
```
• Default parameter should be set to immutable type (number, string, tuple)
```def function(ls=[]):
print(id(ls))
ls.append(1)
print(id(ls))
print(ls)

function()
```
```1759752744328
1759752744328

```
```function()
```
```1759752744328
1759752744328
[1, 1]
```
```function()
```
```1759752744328
1759752744328
[1, 1, 1]
```
```def function(ls="Python"):
print(id(ls))
ls += "3.7"
print(id(ls))
print(ls)

function()
```
```1759701700656
1759754352240
Python3.7
```
```function()
```
```1759701700656
1759754353328
Python3.7
```
```function()
```
```1759701700656
1759754354352
Python3.7
```
• Make parameters optional
```def name(first_name, last_name, middle_name=None):
if middle_name:
return first_name+middle_name+last_name
else:
return first_name+last_name

print(name("large","Child"))
print(name("large", "Child", "Jie"))
```
```Tsotsi
Da Jie Zi
```

*4. Variable length parameter   args

• I don't know how many parameters * args will be passed

• The parameter must be placed at the end of the parameter list

```def foo(x, y, z, *args):
print(x, y ,z)
print(args)

foo(1, 2, 3, 4, 5, 6)    # Redundant parameters, packed and passed to args
```
```1 2 3
(4, 5, 6)
```
• Dispersion of real evidence
```def foo(x, y, z, *args):
print(x, y ,z)
print(args)

foo(1, 2, 3, [4, 5, 6])
```
```1 2 3
([4, 5, 6],)
```
```foo(1, 2, 3, *[4, 5, 6])   # A list, string, tuple, or collection is broken up
```
```1 2 3
(4, 5, 6)
```

**5. Variable length parameter

```def foo(x, y, z, **kwargs):
print(x, y ,z)
print(kwargs)

foo(1, 2, 3, a=4, b=5, c=6)    #  Redundant parameters, packaged as dictionaries and passed to kwargs
```
```1 2 3
{'a': 4, 'b': 5, 'c': 6}
```
• Dictionary argument break up
```def foo(x, y, z, **kwargs):
print(x, y ,z)
print(kwargs)

foo(1, 2, 3, **{"a": 4, "b": 5, "c":6})
```
```1 2 3
{'a': 4, 'b': 5, 'c': 6}
```
• The combination of variable length parameters
```def foo(*args, **kwargs):
print(args)
print(kwargs)

foo(1, 2, 3, a=4, b=5, c=6)
```
```(1, 2, 3)
{'a': 4, 'b': 5, 'c': 6}
```

### 4.1.4 function body and variable scope

• A function body is a piece of code that only executes when a function is called. The code structure is no different from other codes

• Local variables - defined and functioning only within a function body

```def multipy(x, y):
z = x*y
return z

multipy(2, 9)
print(z)            # After the function is executed, the local variable z has been released
```
```---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

<ipython-input-29-9a7fd4c4c0a9> in <module>
5
6 multipy(2, 9)
----> 7 print(z)            # After the function is executed, the local variable z has been released

NameError: name 'z' is not defined
```
• Global variables - External definitions are all global variables

• Global variables can be used directly within a function body

```n = 3
ls = 
def multipy(x, y):
z = n*x*y
ls.append(z)
return z

print(multipy(2, 9))
ls
```
```54
[0, 54]
```
• Defining global variables in function body through global
```def multipy(x, y):
global z
z = x*y
return z

print(multipy(2, 9))
print(z)
```
```18
18
```

### 4.1.5 return value

1. Single return value

```def foo(x):
return x**2

res = foo(10)
res
```
```100
```

2. Multiple return values -- in tuples

```def foo(x):
return 1, x, x**2, x**3    # Comma separated, pack return

print(foo(3))
```
```(1, 3, 9, 27)
```
```a, b , c, d = foo(3)       # Unpacking assignment
print(a)
print(b)
print(c)
print(d)
```
```1
3
9
27
```

3. There can be multiple return statements. Once one of them is executed, it represents the end of function operation

```def is_holiday(day):
if day in ["Sunday", "Saturday"]:
return "Is holiday"
else:
return "Not holiday"
print("La demacia la la la la la la la")       # You don't have a chance to run...

print(is_holiday("Sunday"))
print(is_holiday("Monday"))
```
```Is holiday
Not holiday
```

4. No return statement, return value is None

```def foo():
print("I'm Monkey King")

res = foo()
print(res)
```
```I'm Monkey King
None
```

### 4.1.6 suggestions

1. Naming of functions and their parameters naming of reference variables

• Combination of lowercase and underline

• Practical significance

2. It should include comments that briefly describe the function functions, followed by the function definition

```def foo():
# The purpose of this function is to show you, what do you see, how do you....
pass
```

3. Two blank lines before and after function definition

```def f1():
pass

# Empty two lines to show innocence
def f2():
pass

def f3(x=3):    # No space is required on both sides of equal sign of default parameter assignment
pass

# ...
```

4. No space is required on both sides of equal sign of default parameter assignment

## 4.2 example of functional programming

Modular programming idea

• Divide and rule from top to bottom

[problem description]

• Xiaodan and Xiaowei play badminton well, and their level is also between Bo Zhong. Xiaodan is a little better. Basically, playing 100 balls, Xiaodan can win 55 times, and Xiaowei can win 45 times.

• But every time in a big game (the winner is determined in the first set, who wins 21 points first, who wins), Xiaodan's probability of winning is far greater than Xiaowei, Xiaowei is very unconvinced.

• Dear friends, can you reveal the mystery through simulation experiments?

[problem abstraction]

1. In Xiaodan Vs Xiaowei's binary game system, Xiaodan has a 55% winning probability per ball and Xiaowei has a 45% winning probability per ball;

2. In each game, whoever wins 21 goals (21 points) first wins;

3. Assuming an independent game of n = 10000, how many games will Xiao Dan win? (when n is large, the experimental result is about the real expectation)

[problem decomposition]

```def main():
# Main logic
prob_A, prob_B, number_of_games = get_inputs()                        # Get raw data
win_A, win_B = sim_n_games(prob_A, prob_B, number_of_games)           # Get simulation results
print_summary(win_A, win_B, number_of_games)                          # Result summary output
```

1. Input raw data

```def get_inputs():
# Input raw data
prob_A = eval(input("Please enter athletes A Win probability per ball of(0~1): "))
prob_B = round(1-prob_A, 2)
number_of_games = eval(input("Please enter the number of analog fields (positive integer):"))
print("Total number of simulation competitions:", number_of_games)
print("A Winning probability of each ball:", prob_A)
print("B Winning probability of each ball:", prob_B)
return prob_A, prob_B, number_of_games
```

Unit test

```prob_A, prob_B, number_of_games = get_inputs()
print(prob_A, prob_B, number_of_games)
```
```Please input player A's winning probability per ball (0-1): 0.55
Please input the number of simulated fields (positive integer): 10000
Total number of simulation competitions: 10000
Player A's winning probability per ball: 0.55
Player B's winning probability per ball: 0.45
0.55 0.45 10000
```

2. Multiple game simulation

```def sim_n_games(prob_A, prob_B, number_of_games):
# Simulate the results of multiple games
win_A, win_B = 0, 0                # Initialize the winning matches of A and B
for i in range(number_of_games):   # Number of iterations
score_A, score_B = sim_one_game(prob_A, prob_B)  # Get the score of the simulation match in turn
if score_A > score_B:
win_A += 1
else:
win_B += 1
return win_A, win_B
```
```import random
def sim_one_game(prob_A, prob_B):
# Simulate the outcome of a game
score_A, score_B = 0, 0
while not game_over(score_A, score_B):
if random.random() < prob_A:                # random.random() produces random decimals between [0,1], evenly distributed
score_A += 1
else:
score_B += 1
return score_A, score_B
```
```def game_over(score_A, score_B):
# The end condition of single simulation: one side reaches 21 points first, and the game is over
return score_A == 21 or score_B == 21
```

assert for unit test -- assertion

• assert expression

• Trigger exception when expression result is false

```assert game_over(21, 8) == True
assert game_over(9, 21) == True
assert game_over(11, 8) == False
assert game_over(21, 8) == False
```
```---------------------------------------------------------------------------

AssertionError                            Traceback (most recent call last)

<ipython-input-42-88b651626036> in <module>
2 assert game_over(9, 21) == True
3 assert game_over(11, 8) == False
----> 4 assert game_over(21, 8) == False

AssertionError:
```
```print(sim_one_game(0.55, 0.45))
print(sim_one_game(0.7, 0.3))
print(sim_one_game(0.2, 0.8))
```
```(21, 7)
(21, 14)
(10, 21)
```
```print(sim_n_games(0.55, 0.45, 1000))
```
```(731, 269)
```

3. Result summary output

```def print_summary(win_A, win_B, number_of_games):
# Result summary output
print("Co simulation{}Match".format(number_of_games))
print("Player A Win victory{0}Field ratio{1:.1%}".format(win_A, win_A/number_of_games))
print("Player B Win victory{0}Field ratio{1:.1%}".format(win_B, win_B/number_of_games))
```
```print_summary(729, 271, 1000)
```
```1000 games simulated
Player A won 729 games, accounting for 72.9%
Player B won 271 games, accounting for 27.1%
```
```import random

def get_inputs():
# Input raw data
prob_A = eval(input("Please enter athletes A Win probability per ball of(0~1): "))
prob_B = round(1-prob_A, 2)
number_of_games = eval(input("Please enter the number of analog fields (positive integer):"))
print("Total number of simulation competitions:", number_of_games)
print("A Winning probability of each ball:", prob_A)
print("B Winning probability of each ball:", prob_B)
return prob_A, prob_B, number_of_games

def game_over(score_A, score_B):
# The end condition of single simulation: one side reaches 21 points first, and the game is over
return score_A == 21 or score_B == 21

def sim_one_game(prob_A, prob_B):
# Simulate the outcome of a game
score_A, score_B = 0, 0
while not game_over(score_A, score_B):
if random.random() < prob_A:                # random.random() produces random decimals between [0,1], evenly distributed
score_A += 1
else:
score_B += 1
return score_A, score_B

def sim_n_games(prob_A, prob_B, number_of_games):
# Simulate the results of multiple games
win_A, win_B = 0, 0                # Initialize the winning matches of A and B
for i in range(number_of_games):   # Number of iterations
score_A, score_B = sim_one_game(prob_A, prob_B)  # Get the score of the simulation match in turn
if score_A > score_B:
win_A += 1
else:
win_B += 1
return win_A, win_B

def print_summary(win_A, win_B, number_of_games):
# Result summary output
print("Co simulation{}Match".format(number_of_games))
print("\033[31m Player A Win victory{0}Field ratio{1:.1%}".format(win_A, win_A/number_of_games))
print("Player B Win victory{0}Field ratio{1:.1%}".format(win_B, win_B/number_of_games))

def main():
# Main logic
prob_A, prob_B, number_of_games = get_inputs()                        # Get raw data
win_A, win_B = sim_n_games(prob_A, prob_B, number_of_games)           # Get simulation results
print_summary(win_A, win_B, number_of_games)                          # Result summary output

if __name__ == "__main__":
main()
```
```Please input player A's winning probability per ball (0-1): 0.52
Please input the number of simulated fields (positive integer): 10000
Total number of simulation competitions: 10000
Player A's winning probability per ball: 0.52
Player B's winning probability per ball: 0.48
10000 games simulated
[31m player A won 6033 games, accounting for 60.3%
Player B won 3967 games, accounting for 39.7%
```

According to statistics, Xiaodan and Xiaowei have played 40 times in 14 years. Xiaodan leads by 28:12.

Among them, the two engaged in a total of 100 rounds:

Xiaodan won 61 games, accounting for 61%;

Xiaowei won 39 games, accounting for 39%.

## 4.3 anonymous functions

1. Basic form

lambda variables: function bodies

2. Common usage

Anonymous functions are best used in parameter lists, especially with key =

• Sort() sorted()
```ls = [(93, 88), (79, 100), (86, 71), (85, 85), (76, 94)]
ls.sort()
ls
```
```[(76, 94), (79, 100), (85, 85), (86, 71), (93, 88)]
```
```ls.sort(key = lambda x: x)
ls
```
```[(86, 71), (85, 85), (93, 88), (76, 94), (79, 100)]
```
```ls = [(93, 88), (79, 100), (86, 71), (85, 85), (76, 94)]
temp = sorted(ls, key = lambda x: x+x, reverse=True)
temp
```
```[(93, 88), (79, 100), (85, 85), (76, 94), (86, 71)]
```
• max() min()
```ls = [(93, 88), (79, 100), (86, 71), (85, 85), (76, 94)]
n = max(ls, key = lambda x: x)
n
```
```(79, 100)
```
```n = min(ls, key = lambda x: x)
n
```
```(86, 71)
```

## 4.4 process and object oriented

Process oriented -- process centered programming idea, with "what is happening" as the main goal of programming. Cold, programmed

Object oriented: abstract things in the real world into objects, pay more attention to "who is affected" and be closer to reality. Flesh and blood, anthropomorphic

• Take the bus as an example

"Process oriented": car start is one event, car arrival is another event....

When programming, we are concerned with an event, not the car itself.

We write programs for startup and arrival respectively.

"Object oriented": construct the object of "car".

The object includes a series of "attributes" such as power, service time, manufacturer, etc;

It also includes a series of "methods" such as refueling, starting, acceleration, braking, turning, honking, arrival, maintenance, etc.

Express corresponding events through the behavior of objects     Published 9 original articles, won praise 1, visited 98

Topics: IPython Programming Lambda less