41  函数 定义、调用、作用域

本章定位(复习与补充训练层):本章对应正课第3章《函数定义 算术平均收益率计算》(章节 3),并与第45章《Python自定义函数》(章节 46)互为补充训练,用于复习、补缺与额外练习。建议先不看讲解,直接尝试下方平台任务,再对照解析补弱项。本章不属于必修主线。先做本章『动手与思考』第 1 题与平台任务自测,通过即可跳过本章。

41.1 引言函数式编程的革命

函数(Function)是编程中最基本也是最重要的抽象机制:把一段计算封装成可复用、可测试、可读的单元,让策略、指标与风险度量都能以参数化的方式反复调用。本章用两个平台任务检验你对函数定义、参数传递与作用域的复习效果。

41.2 本章学习目标

本章为复习与补充训练,目标是检验你是否能脱离正课独立完成下列任务:

  1. 能独立写出完整的函数定义:说明 def、参数、文档字符串、return 各自的作用,并独立完成税后工资函数 calculate_tax(salary) 的定义与调用
  2. 能独立完成平台任务一:读懂用 input() 输入基本工资、按阈值判定税率并输出税后工资的脚本,并说出它与函数封装版本的等价关系
  3. 能独立完成平台任务二:定义现值函数 PV(R, *NCF),用可变参数接收任意期现金流,借助 pow()round() 逐期贴现累加并输出
  4. 能区分位置参数与关键字参数,会为函数设计默认参数,并能说出可变默认参数的陷阱及 None 惯用法
  5. 能按 LEGB 规则判断变量的可见范围,说明函数内重新绑定全局变量时为何需要 global 声明

若上述任务无法独立完成,请回到正课第3章对应小节补弱,再回到本章练习。

41.3 函数定义与调用基础

复习语法细节之前,先明确函数为什么值得封装——它在软件工程与金融分析中的价值是后面一切语法设计的出发点:

函数的核心价值

在软件开发和数据分析中,函数带来了五个不可替代的价值:

  1. 抽象化(Abstraction): 函数将复杂的实现细节隐藏在简洁的接口之后,使程序员能够关注”做什么”而非”怎么做”

  2. 模块化(Modularization): 通过将大问题分解为小函数,每个函数专注于单一任务,遵循单一职责原则(Single Responsibility Principle)

  3. 复用性(Reusability): 一次编写,多处调用。这不仅节省了开发时间,更重要的是减少了出错机会

  4. 可测试性(Testability): 独立的函数更容易进行单元测试,可以验证其正确性

  5. 可读性(Readability): 函数名本身就是最好的文档。calculate_sharpe_ratio()比一段内联的代码更能传达意图

在金融分析中的特殊意义

在金融数据分析和量化交易中,函数的重要性更加突出:

  • 策略封装: 交易策略可以作为函数实现,参数化配置
  • 指标计算: 技术指标(如MA、MACD、RSI)适合封装为函数
  • 风险管理: VaR、最大回撤等风险度量都可以函数化
  • 回测框架: 整个回测流程就是一系列函数的组合

理论背景:函数定义的解剖学

一个完整的Python函数定义包含以下要素:

  1. def关键字: 告诉Python我们要定义一个函数(define的缩写)
  2. 函数名: 遵循Python命名规范,使用小写字母和下划线(snake_case)
  3. 参数列表: 函数的输入,放在圆括号内
  4. 冒号: 表示函数头部的结束
  5. 文档字符串(Docstring): 三引号包围的字符串,用于说明函数用途
  6. 函数体: 缩进的代码块,包含执行的语句
  7. return语句: 返回函数结果
列表 41.1: 函数定义与调用示例
# =============================================================================
# 示例:定义和调用函数计算税后工资
# =============================================================================
# 本示例演示Python函数的完整定义和调用过程,包括参数、返回值和文档字符串

# ==================== 函数定义部分 ====================
# def关键字用于定义函数
#   - def是"define"(定义)的缩写
#   - 告诉Python解释器:我们要定义一个新的函数
#
# 函数命名规范:
#   - 函数名:calculate_tax
#   - 使用小写字母
#   - 多个单词之间用下划线连接(snake_case风格)
#   - 函数名应该清晰描述函数的功能(这里计算税收)
#
# 参数列表:
#   - salary是函数的参数(parameter)
#   - 参数放在圆括号()内
#   - 参数是函数的输入,类似数学函数f(x)中的x
#   - 这里salary表示税前工资,数据类型应该是数字
def calculate_tax(salary):

    # ==================== 文档字符串 ====================
    # 三引号"""包围的文本是函数的文档字符串(docstring)
    # 文档字符串是函数的"使用说明书",应该包含:
    #   1. 函数功能的简要描述
    #   2. 参数说明(参数名、类型、含义)
    #   3. 返回值说明(类型、含义)
    #   4. 使用示例或注意事项(可选)
    #
    # 可以通过help(calculate_tax)命令查看这个文档字符串
    """
    计算税后工资

    参数:
        salary (float): 税前工资,单位为元

    返回:
        float: 税后工资,单位为元

    计算规则:
        - 不超过3000元:不征税,税率为0%
        - 超过3000元:对超出部分征收5%的税
    """

    # ==================== 函数体:核心逻辑 ====================
    # 函数体是缩进的代码块,包含函数要执行的所有语句
    # Python使用缩进(通常是4个空格)来表示代码块的层次关系

    # 第一步:判断工资是否超过3000元
    # if语句是条件判断语句
    #   - if是Python关键字,表示"如果"
    #   - salary <= 3000是条件表达式
    #   - <=是比较运算符,表示"小于或等于"
    #   - 如果条件为真(True),执行冒号后的缩进代码块
    if salary <= 3000:
        # 工资不超过3000元时的处理
        # rate变量存储税率
        # =是赋值运算符,将右侧的值赋给左侧的变量
        # 0表示0%的税率,即不征税
        rate = 0
    else:
        # else语句与if配对,表示"否则"
        # 当if条件为假(False)时,执行else后的代码块
        # 工资超过3000元时的处理
        # 0.05表示5%的税率(小数形式)
        rate = 0.05

    # 第二步:计算应缴税额
    # 税额 = (工资 - 免税额度) × 税率
    # 这里3000是免税额度,只有超出部分才需要征税
    # 圆括号用于改变运算优先级,先计算减法,再计算乘法
    tax = (salary - 3000) * rate

    # 第三步:计算税后工资
    # 税后工资 = 税前工资 - 应缴税额
    # 这是一个简单的减法运算
    after_tax = salary - tax

    # 第四步:返回计算结果
    # return关键字将结果返回给函数的调用者
    #   - return后跟要返回的值或表达式
    #   - 执行return后,函数立即结束,后续代码不会执行
    #   - 如果没有return语句,函数返回None
    #   - 这里返回税后工资的计算结果
    return after_tax

# ==================== 函数调用部分 ====================
# 函数定义完成后,需要调用才能执行
# 函数调用的语法:函数名(参数值)

# 调用calculate_tax函数
#   - calculate_tax是函数名
#   - 5000是实际参数(argument),传入给函数
#   - 5000表示税前工资为5000元
#   - 函数执行后,return语句返回税后工资
#   - 返回值赋值给变量result存储
result = calculate_tax(5000)
# 税收计算过程:
#   salary = 5000
#   因为5000 > 3000,所以rate = 0.05(5%)
#   tax = (5000 - 3000) × 0.05 = 2000 × 0.05 = 100元
#   after_tax = 5000 - 100 = 4900元
#   result = 4900

# ==================== 输出结果 ====================
# 使用f-string格式化字符串输出结果
# f-string是Python 3.6+引入的字符串格式化方法
#   - f表示format(格式化)
#   - 花括号{}内可以放入变量或表达式
#   - :.0f是格式化说明符
#     - :表示格式化选项的开始
#     - .0表示保留0位小数
#     - f表示浮点数(float)
#   - 整体意思是:将result格式化为不显示小数的浮点数
print(f'税后工资: {result:.0f}元')
# 预期输出: 税后工资: 4900元

代码深度解析:

  1. 函数定义的执行时机:

    • 定义函数时,代码不会立即执行
    • 只有在调用函数时,函数体内的代码才会运行
  2. 参数传递:

    # salary是形式参数(formal parameter),占位符
    # 5000是实际参数(actual parameter),实际传入的值
  3. return语句:

    • return将结果返回给调用者
    • 执行return后,函数立即结束,后续代码不会执行
    • 如果没有return语句,函数返回None
  4. 文档字符串的重要性:

    • 这是函数的”使用说明书”
    • 可以通过help(calculate_tax)查看
    • 专业代码都应该有完整的文档字符串

41.4 参数传递:灵活性与安全性的平衡

Python提供了丰富的参数传递机制,既保证了使用的灵活性,又维持了必要的安全性。

41.4.1 位置参数与关键字参数

任务要求:从键盘输入基本工资(float),按”不超过3000元税率为0、超过3000元的部分按5%“的规则用 if-else 判定扣税率,计算并按 %d 格式输出税后工资。请在教学平台的交互环境中运行,判定以平台为准。

列表 41.2: 平台原始代码 (1)
# 注:该代码块包含input()交互输入,需在平台环境运行
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
#题目一
salary = float(input("请输入基本工资:"))  # 从键盘上输入基本工资
if salary <= 3000:  # 判断基本工资是否小于等于3000
    rate = 0  # 基本工资小于等于3000,不扣税,即扣税率为0%
else:  # 不满足以上条件时
    rate = 0.05  # 基本工资打印300,扣税率为0.05,即5%

# 计算税后工资,基本工资-扣税,扣税额为超过3000部分的乘以扣税率
salary = salary - (salary - 3000) * rate
print("税后工资为:%d" % salary)  # 将税后工资打印输出

预期输出(判读要点,以平台运行结果为准):该代码块包含 input() 交互输入,须在教学平台环境运行。判读要点:程序提示”请输入基本工资:“并等待输入;输入不超过3000时税率取0,税后工资与输入相同;超过3000时对超出部分按5%扣税。本机以管道输入模拟交互实测(输入 5000 时输出 税后工资为:4900,输入 3000 时输出 税后工资为:3000),输入 5000 的完整输出如下:

请输入基本工资:税后工资为:4900

位置参数 vs 关键字参数:

特性 位置参数 关键字参数
传递方式 按顺序传递 按名称传递
顺序要求 必须正确 可以任意
可读性 较差(容易混淆) 较好(明确清晰)
使用场景 参数少且类型不同 参数多或类型相似

41.4.2 默认参数:提高函数易用性

列表 41.3: 默认参数的使用
# 定义带有默认参数的函数
# greeting参数有默认值'您好',调用时可以省略
def greet2(name, greeting='您好'):
    """
    生成问候语(带默认值)

    参数:
        name (str): 人名
        greeting (str): 问候语,默认为'您好'

    返回:
        str: 完整的问候语
    """
    # 格式化并返回问候语
    return f'{greeting}, {name}!'

# 调用方式1:只提供必填参数
# greeting使用默认值'您好'
print(greet2('王五'))

# 调用方式2:覆盖默认值
# 显式指定greeting为'早安'
print(greet2('赵六', greeting='早安'))

默认参数的设计原则:

  1. 必填参数在前: 没有默认值的参数必须放在前面
  2. 默认参数在后: 有默认值的参数必须放在后面
  3. 不可变对象: 默认值最好使用不可变对象(如数字、字符串、元组)

警告:可变默认参数陷阱:

# 危险示例:使用列表作为默认值
def add_item(item, items=[]):  # 危险!
    items.append(item)
    return items

# 第一次调用
print(add_item('A'))  # ['A']

# 第二次调用:问题出现了!
print(add_item('B'))  # ['A', 'B'] 而不是 ['B']!

# 正确做法:使用None作为默认值
def add_item_correct(item, items=None):
    if items is None:
        items = []  # 每次调用都创建新列表
    items.append(item)
    return items

print(add_item_correct('A'))  # ['A']
print(add_item_correct('B'))  # ['B'] 符合预期!

41.5 可变参数:处理任意数量的输入

**理论背景:*args和kwargs的设计哲学

Python中的*args**kwargs提供了处理可变参数的强大能力:

  • *args: 收集所有额外的位置参数,打包成元组
  • **kwargs: 收集所有额外的关键字参数,打包成字典
列表 41.4: 可变参数与关键字参数
def summary(*args, **kwargs):
    """
    演示可变参数的使用

    参数:
        *args: 可变数量的位置参数(收集为元组)
        **kwargs: 可变数量的关键字参数(收集为字典)

    返回:
        None: 此函数仅用于演示,不返回值
    """
    # 打印所有位置参数
    print(f'位置参数: {args}')

    # 打印所有关键字参数
    print(f'关键字参数: {kwargs}')

    # 如果有位置参数,计算它们的和
    if args:
        total = sum(args)  # sum()函数计算元组所有元素的和
        print(f'和: {total}')

    # 如果有关键字参数,显示数量
    if kwargs:
        print(f'键值对数量: {len(kwargs)}')

# 调用示例1:只传递位置参数
# 1, 2, 3, 4, 5被收集到args元组中
summary(1, 2, 3, 4, 5)

# 调用示例2:只传递关键字参数
# a=1, b=2, c=3被收集到kwargs字典中
summary(a=1, b=2, c=3)

# 调用示例3:混合传递
# 1, 2被收集到args元组中
# x=10, y=20被收集到kwargs字典中
summary(1, 2, x=10, y=20)

可变参数的金融应用:

# 应用1:计算多只股票的加权收益率
def weighted_return(*returns, **weights):
    """
    计算加权平均收益率

    参数:
        *returns: 多个收益率值
        **weights: 权重参数,如w1=0.3, w2=0.7

    返回:
        float: 加权平均收益率
    """
    # 检查收益率和权重数量是否匹配
    if len(returns) != len(weights):
        raise ValueError('收益率和权重数量不匹配')

    # 计算加权平均
    total = sum(r * w for r, w in zip(returns, weights.values()))
    return total

# 使用示例
result = weighted_return(0.05, 0.03, 0.08, w1=0.5, w2=0.3, w3=0.2)
print(f'加权收益率: {result:.2%}')

41.6 作用域:变量的可见性与生命周期

理论背景:LEGB规则

Python使用LEGB规则来查找变量,代表四个层级的作用域:

  1. L(Local): 局部作用域(函数内部)
  2. E(Enclosing): 嵌套函数的外层函数作用域
  3. G(Global): 全局作用域(模块级别)
  4. B(Built-in): 内置作用域(Python内置模块)

任务要求:定义现值函数 PV(R, *NCF)——给定贴现率 R 与任意期现金流,按年间隔逐期折现并累加得到现值、输出结果;随后用两组不同期数的现金流调用该函数,体会 *NCF 可变参数的接收方式。请将代码原样输入教学平台(注释除外),判定以平台为准。

列表 41.5: 平台原始代码 (2)
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
#需要传入的参数,期数以及每期的现金流,单位为元。
def PV(R,*NCF):
    pv=0                         #初始化,后续要累加
    n=1                          #间隔为1年
    for cf in NCF:  # 遍历NCF中的每个cf
        pv+=round(cf/pow((1+R),n),2)   #pow()是幂函数
        n+=1  # 更新n的值
    return print("现值结果是:{:.2f}元".format(pv))  # 返回计算结果

#调用自定义的现值函数PV()
PV(0.05,-10000,8000,12000)
PV(0.05,-20000,-500,2000,10000,16000,30000)  # 调用自定义的现值函数,传入利率与各期现金流

预期输出(本机实际运行结果,具体以平台运行结果为准):

现值结果是:8098.48元
现值结果是:25376.45元

作用域的金融应用:

# 全局配置:交易系统的参数
MAX_POSITION = 1000000  # 最大持仓金额(元)
RISK_LIMIT = 0.02       # 风险限制(2%)

def calculate_position_size(capital, risk_level):
    """
    根据资金和风险水平计算持仓规模

    参数:
        capital (float): 可用资金
        risk_level (float): 风险水平(0-1之间)

    返回:
        float: 建议持仓金额
    """
    # 使用全局变量进行风险控制
    if risk_level > RISK_LIMIT:
        # 风险过高,降低持仓
        position = capital * 0.5
    else:
        position = capital * 0.8

    # 确保不超过最大持仓限制
    return min(position, MAX_POSITION)

# 使用示例
position = calculate_position(500000, 0.03)
print(f'建议持仓: {position:,.0f}元')

global关键字的使用原则:

  1. 尽量避免使用: 全局变量会增加代码耦合度
  2. 明确声明: 如果必须修改全局变量,使用global声明
  3. 替代方案: 使用类(Class)来封装状态和数据

最佳实践总结:

  1. 函数设计:
    • 单一职责:每个函数只做一件事
    • 参数合理:不超过5个位置参数
    • 文档完整:包含参数说明和返回值说明
  2. 参数传递:
    • 位置参数:用于必需的、类型不同的参数
    • 关键字参数:用于可选的、有默认值的参数
    • 默认参数:提高函数易用性,但避免使用可变对象
  3. 作用域管理:
    • 避免全局变量:使用参数传递数据
    • 局部变量优先:限制变量的作用范围
    • 常量大写:全局常量用大写字母命名

函数是Python编程的核心构建块,掌握函数的高级用法对于编写高质量代码至关重要。在金融分析中,合理的函数设计能够显著提高代码的可读性、可维护性和复用性。

41.7 延伸阅读(选读)

函数概念从早期数学符号系统、λ 演算,到现代语言中”函数作为一等公民”的函数式复兴,演进脉络与分阶段详情见第 章节 46 章的延伸阅读,此处不再重复。

41.8 本章小结

要点:

  • 函数定义七要素:def、函数名、参数列表、冒号、文档字符串、函数体、return;定义时不执行,调用时才执行
  • 位置参数按顺序传递,关键字参数按名称传递;默认参数必须放在必填参数之后
  • *args 把多余的实参收集为元组,**kwargs 收集为字典;平台任务二的 PV(R, *NCF) 正是用 *NCF 接收任意期现金流
  • 作用域查找遵循 LEGB(Local→Enclosing→Global→Built-in);函数内可直接读取全局变量,重新绑定则需要 global
  • 好的函数单一职责、参数精炼、文档完整,return 返回结果而不是只 print

易错点:

  • 没有 return 的函数返回 None;执行到 return 后函数立即结束
  • 平台任务二写的是 return print(...),函数实际返回的是 print 的返回值 None;自己封装时建议 return pv,再在调用处打印
  • 可变默认参数陷阱:def f(item, items=[]) 的默认列表在多次调用间共享,应改用 items=None 后在函数内新建
  • 必填参数写在默认参数之后会直接报 SyntaxError

41.9 动手与思考

以下练习每题附参考答案(默认折叠)。请先独立完成并写下你的判断,再点开对照,最后上机验证。

  1. 概念自测(不看正课):形参与实参的区别是什么?*args**kwargs 分别把多余参数收集成什么类型?LEGB 的查找顺序是怎样的?

    参考答案(点开前请先独立完成)

    解题思路:形参是函数定义时括号里占位的变量名(如 def f(x, rate=0.05) 中的 xrate),实参是调用时实际传入的值(如 f(6000, rate=0.1) 中的 6000 与 0.1);调用时实参按位置或关键字绑定给形参。*args 把多余的位置参数收集成元组,**kwargs 把多余的关键字参数收集成字典。LEGB 查找顺序:Local(函数内部)→ Enclosing(外层嵌套函数)→ Global(模块级)→ Built-in(内置),由内向外逐层查找、先找到先用。

    回扣主线章:函数定义与调用的系统讲解见第 章节 3 章。

  2. 输出预测:不运行代码,先写出下面代码的输出结果,再上机检验你的判断。

    def f(x, rate=0.05):
        if x <= 3000:
            t = 0
        else:
            t = (x - 3000) * rate
        return x - t
    
    print(f(5000))
    print(f(3000))
    print(f(6000, rate=0.1))
    
    def add_item(item, items=[]):
        items.append(item)
        return items
    
    print(add_item('A'))
    print(add_item('B'))

    参考答案(先写下你的预测再点开)

    解题思路f(5000) 未传 rate、用默认值 0.05,税额 (5000−3000)×0.05=100,返回 4900.0;f(3000) 落在 x <= 3000 分支,税额 0,返回整数 3000;f(6000, rate=0.1) 用关键字参数覆盖默认值,税额 (6000−3000)×0.1=300,返回 5700.0。add_item 的默认参数 items=[] 是可变默认参数陷阱——默认列表在函数定义时只创建一次、所有调用共享:第一次调用后它已是 ['A'],第二次再追加 'B'['A', 'B'],而不是新建空列表。

    # 验证脚本:原样运行题面代码
    def f(x, rate=0.05):  # rate为默认参数
        if x <= 3000:  # 未超免征额
            t = 0  # 税额为0
        else:
            t = (x - 3000) * rate  # 超出部分计税
        return x - t  # 返回税后金额
    
    print(f(5000))  # 用默认税率调用
    print(f(3000))  # 恰在免征边界
    print(f(6000, rate=0.1))  # 关键字参数覆盖默认税率
    
    def add_item(item, items=[]):  # 可变默认参数(陷阱示范)
        items.append(item)  # 向默认列表追加元素
        return items  # 返回列表
    
    print(add_item('A'))  # 第一次调用
    print(add_item('B'))  # 第二次调用,复用同一默认列表

    预期输出(本机 peter 环境实际运行结果,具体以平台运行结果为准):

    4900.0
    3000
    5700.0
    ['A']
    ['A', 'B']

    回扣主线章:默认参数与可变默认参数陷阱的讲解见第 章节 3 章。

  3. 动手验证:编写函数 after_tax(salary, base=3000, rate=0.05) 返回税后工资,分别用位置参数、关键字参数两种方式调用并输出;再构造一种会报错的调用(例如缺少必填参数)并解释错误信息。

    参考答案(点开前请先独立完成)

    解题思路after_tax(8000, 3000, 0.05) 全按位置绑定(8000→salary、3000→base、0.05→rate),after_tax(salary=8000, rate=0.05) 按关键字绑定、base 用默认值,两者都输出 7750.0(税额 (8000−3000)×0.05=250)。报错调用 after_tax() 缺少必填的位置参数 salary,抛 TypeError: after_tax() missing 1 required positional argument: 'salary'——信息明确指出缺的是哪个必填参数。

    # 验证脚本:两种调用方式对照,以及缺参报错
    def after_tax(salary, base=3000, rate=0.05):  # salary必填,base与rate有默认值
        if salary <= base:
            return salary  # 未超免征额,不扣税
        return salary - (salary - base) * rate  # 超出部分计税后返回
    
    print(after_tax(8000, 3000, 0.05))  # 位置参数调用:三个实参按顺序绑定
    print(after_tax(salary=8000, rate=0.05))  # 关键字参数调用:base用默认值
    try:
        after_tax()  # 缺少必填参数salary(预期报错)
    except TypeError as error_msg:
        print('错误信息:', error_msg)  # 捕获并显示错误信息

    预期输出(本机 peter 环境实际运行结果,具体以平台运行结果为准):

    7750.0
    7750.0
    错误信息: after_tax() missing 1 required positional argument: 'salary'

    回扣主线章:位置参数、关键字参数与默认参数的绑定规则见第 章节 3 章。

  4. 变式任务(平台任务二同型改造):仿照 PV(R, *NCF) 的写法,定义终值函数 FV(R, *CF),把各期现金流按复利滚算到最后一期并求和,调用 FV(0.05, -10000, 8000, 12000) 输出结果。

    参考答案(点开前请先独立完成)

    解题思路:与 PV(R, *NCF) 镜像对称——PV 把第 \(n\) 期现金流除以 \((1+R)^n\) 折现到期初,FV 把第 \(n\) 期现金流乘以 \((1+R)^{N-n}\) 滚算到最后一期(\(N\) 为现金流总期数)。调用 FV(0.05, -10000, 8000, 12000)\(N=3\)\(-10000\times1.05^{2}+8000\times1.05+12000=-11025+8400+12000=9375\),输出 9375.00 元。

    # 变式程序:终值函数FV,各期现金流滚算到最后一期求和
    def FV(R, *CF):  # R为利率,*CF收集各期现金流为元组
        fv = 0  # 初始化终值累加器
        last_period = len(CF)  # 最后一期的期数
        n = 1  # 当前现金流所在期数
        for cf in CF:  # 遍历各期现金流
            fv += round(cf * pow((1 + R), (last_period - n)), 2)  # 第n期现金流复利滚算到最后一期并累加
            n += 1  # 期数推进
        return print('终值结果是:{:.2f}元'.format(fv))  # 输出终值结果
    
    FV(0.05, -10000, 8000, 12000)  # 调用:期初投入1万,随后两期回收8千与1.2万

    预期输出(本机 peter 环境实际运行结果,具体以平台运行结果为准):

    终值结果是:9375.00元

    注意:以上为本题变式的独立代码;列表 41.5 对应平台任务的原始代码块仍须原样输入教学平台,不要用本变式替换。

    回扣主线章*NCF 可变参数与现值函数 PV 的同型写法见第 章节 3 章与 列表 41.5