函数的概念及其重要性

函数的概念及其重要性

在前几章中,我们已经介绍了数据的表达和数据处理的控制流程,从而可以编写简单的程序实现特定功能。然而,我们在代码复用性、程序结构框架和代码维护性等方面遇到了一些不便。因此,迫切需要引入一种新的方法来解决这些问题——这就是我们今天要讨论的主题:函数。

为什么使用函数?

函数具有三大重要作用:

  1. 提高代码复用性:将常用代码封装成函数,减少重复。
  2. 分解复杂问题:将复杂问题分解为多个简单问题,便于管理和解决。
  3. 提升代码维护性:只需修改函数内部逻辑,不影响其他部分。

函数的基本结构

函数可以理解为一个“白箱子”,具有输入、处理和输出三个部分。其三要素分别为:

  • 参数(输入)
  • 函数体(处理过程)
  • 返回值(输出)

函数的定义与调用

定义函数

函数定义的基本语法如下:
def 函数名(参数):
函数体
return 返回值

例如,定义一个计算阶乘的函数:
def factorial(n):
result = 1
for i in range(1, n + 1):
result *= i
return result

调用函数

调用函数时,使用函数名并传递参数:
factorial(5)

参数传递

形参与实参

  • 形参:函数定义时的参数。
  • 实参:函数调用时传递的实际值。

位置参数

位置参数按照位置顺序传递:
def function(x, y, z):
print(x, y, z)
function(1, 2, 3)

关键字参数

关键字参数通过参数名传递,打破位置限制:
function(y=1, z=2, x=3)

混合使用

位置参数必须在关键字参数之前:
function(1, y=2, z=3)

默认参数

为某些参数设置默认值:
def register(name, age, sex=‘male’):
print(name, age, sex)

可变参数

  • 单星号 *args 接收多个位置参数:
    def function(x, y, *args):
    print(x, y, args)
    function(1, 2, 3, 4, 5)

  • 双星号 **kwargs 接收多个关键字参数:
    def function(x, y, **kwargs):
    print(x, y, kwargs)
    function(1, 2, a=3, b=4)

函数体与变量作用域

局部变量

仅在函数体内定义的变量:
def function():
z = x * y
return z

全局变量

在外部程序中定义的变量:
n = 10
def function():
global z
z = x * y * n

返回值

返回单个或多个值:
def function():
return value
def function():
return value1, value2

模块化编程实例

羽毛球比赛胜负模拟

主要逻辑
  1. 获取原始数据:get_input()
  2. 模拟多场比赛:sim_n_games()
  3. 汇总输出结果:print_summary()
详细步骤
  1. 获取原始数据
    def get_input():
    prob_a = float(input("Enter probability for A: "))
    prob_b = 1 - prob_a
    num_games = int(input("Enter number of games to simulate: "))
    return prob_a, prob_b, num_games

  2. 模拟单场比赛
    def sim_one_game(prob_a, prob_b):
    score_a = score_b = 0
    while not game_over(score_a, score_b):
    if random.random() < prob_a:
    score_a += 1
    else:
    score_b += 1
    return score_a, score_b

  3. 模拟多场比赛
    def sim_n_games(prob_a, prob_b, num_games):
    wins_a = wins_b = 0
    for _ in range(num_games):
    score_a, score_b = sim_one_game(prob_a, prob_b)
    if score_a > score_b:
    wins_a += 1
    else:
    wins_b += 1
    return wins_a, wins_b

  4. 汇总输出结果
    def print_summary(wins_a, wins_b, num_games):
    print(f"Summary of {num_games} games:“)
    print(f"A won {wins_a / num_games * 100:.2f}%”)
    print(f"B won {wins_b / num_games * 100:.2f}%")

匿名函数

匿名函数使用 lambda 定义,常用于排序和最大/最小值计算:
sorted_list = sorted(data, key=lambda x: x[1])
max_value = max(data, key=lambda x: x[1])

面向过程与面向对象编程

面向过程编程

以事件过程为主线,关注事情的发生过程。

面向对象编程

以对象为核心,关注对象的属性和行为。


函数定义与调用

单选题

  1. 为什么我们要使用函数?
    A. 提高代码复用性
    B. 将复杂的逻辑关系分解成简单逻辑关系的组合
    C. 提高代码维护和管理的效率
    D. 以上都是
    答案: D

  2. 函数的三要素不包括以下哪一项?
    A. 参数
    B. 函数体
    C. 返回值
    D. 注释
    答案: D

  3. 在函数定义时,圆括号里的参数称为?
    A. 实参
    B. 形参
    C. 默认参数
    D. 可变参数
    答案: B

  4. 当函数调用时传递给函数的参数称为?
    A. 形参
    B. 实参
    C. 默认参数
    D. 关键字参数
    答案: B

  5. 哪种参数传递方式适用于参数较少的情况?
    A. 位置参数
    B. 关键字参数
    C. 混合参数
    D. 默认参数
    答案: A

  6. 哪种参数传递方式可以打破位置的限制?
    A. 位置参数
    B. 关键字参数
    C. 混合参数
    D. 默认参数
    答案: B

  7. 关于默认参数,下列说法正确的是?
    A. 默认参数必须放在非默认参数前面
    B. 默认参数必须放在非默认参数后面
    C. 默认参数可以放在任意位置
    D. 默认参数不能是不可变类型
    答案: B

  8. 关于可变参数,下列说法正确的是?
    A. 使用*args可以接收任意多个位置参数
    B. 使用**kwargs可以接收任意多个关键字参数
    C. *args接收的参数会被打包成元组
    D. 以上都是
    答案: D

判断题

  1. 函数体内的变量一定是局部变量。
    答案: 正确

  2. 全局变量可以在函数体内直接访问。
    答案: 正确

  3. 局部变量可以在函数体外部访问。
    答案: 错误

  4. 函数的返回值只能是一个值。
    答案: 错误

  5. 没有return语句的函数返回值是None
    答案: 正确

填空题

  1. 函数的定义关键字是______。
    答案: def

  2. 函数的返回值使用______关键字实现。
    答案: return

  3. 将复杂的逻辑关系分解成简单逻辑关系的组合的思想称为______。
    答案: 分而治之

  4. 函数体内的变量称为______变量。
    答案: 局部

  5. 函数体外部定义的变量称为______变量。
    答案: 全局

编程题

  1. 编写一个函数calculate_factorial,接受一个整数n作为参数,返回n的阶乘。

    def calculate_factorial(n):
        if n == 0 or n == 1:
            return 1
        result = 1
        for i in range(2, n + 1):
            result *= i
        return result
    

    编写一个函数get_input,接受用户输入的小丹和小伟每球获胜的概率以及模拟的比赛场次,并返回这三个值。

def get_input():
    prob_a = float(input("请输入小丹每球获胜的概率(例如0.55): "))
    prob_b = 1 - prob_a
    num_games = int(input("请输入模拟的比赛场次(例如10000): "))
    return prob_a, prob_b, num_games

编写一个函数sim_one_game,模拟一场比赛,接受小丹和小伟每球获胜的概率作为参数,返回比赛结束时双方的得分。

import random

def sim_one_game(prob_a, prob_b):
    score_a = 0
    score_b = 0
    while not game_over(score_a, score_b):
        if random.random() < prob_a:
            score_a += 1
        else:
            score_b += 1
    return score_a, score_b

def game_over(score_a, score_b):
    return score_a >= 21 or score_b >= 21

编写一个函数sim_n_games,模拟多场比赛,接受小丹和小伟每球获胜的概率以及模拟的比赛场次作为参数,返回双方获胜的场次数。

def sim_n_games(prob_a, prob_b, num_games):
    wins_a = 0
    wins_b = 0
    for _ in range(num_games):
        score_a, score_b = sim_one_game(prob_a, prob_b)
        if score_a > score_b:
            wins_a += 1
        else:
            wins_b += 1
    return wins_a, wins_b

编写一个函数print_summary,接受双方获胜的场次数以及模拟的比赛场次作为参数,打印输出比赛结果的汇总。

def print_summary(wins_a, wins_b, num_games):
    print(f"总模拟场次: {num_games}")
    print(f"小丹获胜概率: {wins_a / num_games * 100:.2f}%")
    print(f"小伟获胜概率: {wins_b / num_games * 100:.2f}%")

第六章 函数相关习题

习题一:函数定义与调用

题目:
考虑如下函数定义 function(x, *y, **z),并有如下调用 function(*list('ABC'), 'd', **{'name': 'Sarah', 'age': 18})。请问这段代码是否会报错?如果不会报错,那么输出的结果是什么?

答案:
这段代码不会报错,输出结果为:

  • x: a
  • y: (‘B’, ‘C’, ‘d’)
  • z: {‘name’: ‘Sarah’, ‘age’: 18}

习题二:函数编程改进

题目:
假设有一个乒乓球比赛模拟函数,原始规则为:当某一方得分达到21分时即获胜。现需对函数进行以下改进:

  1. 增加容错功能,当输入的获胜概率不在0到1之间时,提示输入错误并要求重新输入。
  2. 修改获胜规则:当某一方得分达到21分且与对手分差至少为2分时才可获胜。
  3. 将比赛规则改为三局两胜制,率先赢得两局者获胜。

请简述如何实现上述改进。

答案:

  1. 使用while True循环不断接收输入,直到输入正确的获胜概率为止。
  2. 修改获胜条件判断逻辑,确保不仅达到21分,还需与对手分差至少为2分。
  3. 引入两个计数器分别记录双方赢下的局数,当任意一方赢下两局时结束比赛。

习题三:Lambda表达式的应用

题目:
给定一段文本字符串,使用lambda表达式对其进行字符频次统计,并按降序排列。

答案:
首先统计每个字符出现次数,存入字典中;然后利用sorted()函数结合lambda表达式,按照字典value值从大到小排序,具体实现为sorted(d.items(), key=lambda item: item[1], reverse=True)

习题四:Lambda表达式的特性与争议

题目:
简述Python中lambda表达式的三个特性,并谈谈你对lambda表达式在Python社区存在争议的看法。

答案:

  1. 匿名性:lambda表达式没有显式的名称。
  2. 输入输出:由lambda关键字引导参数列表,冒号后跟随返回值表达式。
  3. 简单性:只能包含简单的表达式,无法执行复杂语句(如for/while)。

关于争议,一方面lambda可以使某些场景下的代码更为简洁明了,另一方面若过度使用可能导致代码可读性下降,因此应根据实际情况合理选用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

六月五日

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值