一、函数的定义及调用
- 定义:三要素——参数、函数体、返回值
- 调用:函数名(参数)
二、参数传递
-
形参:函数定义时的参数,即变量名
-
实参:函数调用时的参数,即变量的值
-
位置参数:实参按顺序赋值给形参,必须一一对应,一般在参数较少时用
-
关键字参数:直呼其名地赋值,用于参数较多时
-
位置参数可与关键字参数混合使用,但位置参数必须放在前,不能为同一形参重复赋值
-
默认参数:定义阶段就给形参赋值,放在最后,也可以正常赋值,机器学习库中类的方法中常见,必须为不可变类型
-
让参数变成可选:将不常用的参数赋值为None
-
可变参数 *args:不知道会传过来多少参数args,必须放在参数列表最后
该列表会被打包为元组再赋值给args,可以通过前面加将实参打散,一个一个的赋值给args -
可变长参数 *kwargs:赋值方式与args不同,最后会打包为字典
字典打散也是加** -
可变长参数的组合使用
三、函数体与变量作用域
- 变量
1)局部变量——仅在函数体内定义及作用
2)全局变量——外部定义,可通过global在函数体内定义全局变量 - 返回值
1)单个返回值
2)多个返回值——以元组的方式
可以有多个return,但执行一个即函数调用结束,没有return,返回值为None - 规范
四、函数式编程实例
自顶向下,分而治之
- 问题分解
def main():
#主要逻辑
prob_A, prob_B, number_of_games = get_inputs() # 获取原始数据
win_A, win_B = sim_n_games(prob_A, prob_B, number_of_games) # 获取模拟结果
print_summary(win_A, win_B, number_of_games) # 结果汇总输出
- 输入原始数据
def get_inputs():
#输入原始数据
prob_A = eval(input("请输入运动员A每球获胜的概率(0~1):"))
prob_B = round(1-prob_A, 2)
number_of_games = eval(input("请输入模拟的场次(正整数):"))
print("模拟比赛总次数:", number_of_games)
print("A选手每球获胜概率:", prob_A)
print("B选手每球获胜概率:", prob_B)
return prob_A, prob_B, number_of_games
- 单元测试
prob_A, prob_B, number_of_games = get_inputs()
print(prob_A, prob_B, number_of_games)
测试结果正常:
- 多场比赛模拟:
def sim_n_games(prob_A, prob_B, num_of_games):
# 模拟多场比赛的结果
win_A, win_B = 0, 0 # 初始化A,B获胜的场次
for i in range(num_of_games): # 迭代num_of_games次
score_A, score_B = sim_one_game(prob_A, prob_B) # 获得模拟依次比赛的比分
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):
# 模拟一场比赛的结果
score_A, score_B = 0, 0
while not game_over(score_A, score_B):
# 生成的随机小数落在0~prob_A的区间内则为A赢,超过则为B
if random.random() < prob_A: # random.random()生产[0,1)之间的随机小数,均匀分布
score_A += 1
else:
score_B += 1
return score_A, score_B
def game_over(score_A, score_B):
# 单场模拟结束条件,一方先达到21分,比赛结束
return score_A == 21 or score_B == 21
- 单元测试:assert——断言:表达式结果为false时触发异常
assert game_over(21, 8) == True
assert game_over(9, 21) == True
assert game_over(11, 8) == False
print(sim_one_game(0.55, 0.45))
print(sim_one_game(0.7, 0.3))
print(sim_one_game(0.2, 0.8))
print(sim_n_games(0.55, 0.45, 1000))
- 结果汇总输出
def print_summary(win_A, win_B, number_of_games):
#结果汇总
print("共模拟了{}场比赛".format(number_of_games))
print("选手A获胜{0}场,占比{1:.1%}".format(win_A, win_A/number_of_games))
print("选手B获胜{0}场,占比{1:.1%}".format(win_B, win_B/number_of_games))
print_summary(729, 271, 1000)
import random
def get_inputs():
#输入原始数据
prob_A = eval(input("请输入运动员A每球获胜的概率(0~1):"))
prob_B = round(1-prob_A, 2)
number_of_games = eval(input("请输入模拟的场次(正整数):"))
print("模拟比赛总次数:", number_of_games)
print("A选手每球获胜概率:", prob_A)
print("B选手每球获胜概率:", prob_B)
return prob_A, prob_B, number_of_games
def game_over(score_A, score_B):
# 单场模拟结束条件,一方先达到21分,比赛结束
return score_A == 21 or score_B == 21
def sim_one_game(prob_A, prob_B):
# 模拟一场比赛的结果
score_A, score_B = 0, 0
while not game_over(score_A, score_B):
# 生成的随机小数落在0~prob_A的区间内则为A赢,超过则为B
if random.random() < prob_A: # random.random()生产[0,1)之间的随机小数,均匀分布
score_A += 1
else:
score_B += 1
return score_A, score_B
def sim_n_games(prob_A, prob_B, num_of_games):
# 模拟多场比赛的结果
win_A, win_B = 0, 0 # 初始化A,B获胜的场次
for i in range(num_of_games): # 迭代num_of_games次
score_A, score_B = sim_one_game(prob_A, prob_B) # 获得模拟依次比赛的比分
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):
#结果汇总
print("共模拟了{}场比赛".format(number_of_games))
print("选手A获胜{0}场,占比{1:.1%}".format(win_A, win_A/number_of_games))
print("选手B获胜{0}场,占比{1:.1%}".format(win_B, win_B/number_of_games))
def main():
#主要逻辑
prob_A, prob_B, number_of_games = get_inputs() # 获取原始数据
win_A, win_B = sim_n_games(prob_A, prob_B, number_of_games) # 获取模拟结果
print_summary(win_A, win_B, number_of_games) # 结果汇总输出
#main()
if __name__ == "__main__":
main()
五、匿名函数
- 定义:lambda 变量:函数体
- 常用用法:在参数列表中最适合使用匿名函数,尤其是与key=搭配
1)排序sort(),sorted()
2)max(),min()