函数(Function)是编程中最基本的抽象机制之一。
函数在软件开发和数据分析中带来五个不可替代的价值:
| 价值 | 说明 |
|---|---|
| 抽象化 | 隐藏实现细节,关注”做什么” |
| 模块化 | 大问题分解为小函数,单一职责 |
| 复用性 | 一次编写,多处调用 |
| 可测试性 | 独立函数更容易进行单元测试 |
| 可读性 | 函数名本身就是最好的文档 |
在商业数据分析和决策中,函数的重要性尤为突出:
一个完整的Python函数定义包含以下要素:
def关键字:告诉Python要定义一个函数# 定义函数:计算税后工资
# def关键字 + 函数名(snake_case) + 参数列表
def calculate_tax(salary):
"""
计算税后工资
参数:
salary (float): 税前工资,单位为元
返回:
float: 税后工资,单位为元
计算规则:
- 不超过3000元:不征税
- 超过3000元:对超出部分征收5%的税
"""
# 判断工资是否超过3000元
if salary <= 3000:
rate = 0 # 不征税
else:
rate = 0.05 # 超出部分征收5%
# 计算应缴税额和税后工资
tax = (salary - 3000) * rate
after_tax = salary - tax
# 返回税后工资
return after_tax
# 调用函数:传入5000元工资
result = calculate_tax(5000)
print(f'税后工资: {result:.0f}元')税后工资: 4900元
理解两者的区别是掌握函数的关键:
| 阶段 | 操作 | 说明 |
|---|---|---|
| 定义 | def calculate_tax(salary): |
创建函数,代码不会执行 |
| 调用 | calculate_tax(5000) |
执行函数,传入实际参数 |
salary,定义时的占位符5000,调用时传入的值return将结果返回给调用者# 注:该代码块包含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) # 将税后工资打印输出Python提供了两种基本的参数传递方式:
| 特性 | 位置参数 | 关键字参数 |
|---|---|---|
| 传递方式 | 按顺序传递 | 按名称传递 |
| 顺序要求 | 必须正确 | 可以任意 |
| 可读性 | 较差(容易混淆) | 较好(明确清晰) |
| 使用场景 | 参数少且类型不同 | 参数多或类型相似 |
使用默认参数时需要遵循三个原则:
# ❌ 危险示例:使用列表作为默认值
def add_item_wrong(item, items=[]):
items.append(item)
return items
print('第一次调用:', add_item_wrong('A')) # ['A']
print('第二次调用:', add_item_wrong('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'] ✅第一次调用: ['A']
第二次调用: ['A', 'B']
第一次调用: ['A']
第二次调用: ['B']
Python提供了处理任意数量参数的强大能力:
*args:收集所有额外的位置参数,打包成元组**kwargs:收集所有额外的关键字参数,打包成字典位置参数: (1, 2, 3, 4, 5)
关键字参数: {}
和: 15
--- 关键字参数 ---
位置参数: ()
关键字参数: {'a': 1, 'b': 2, 'c': 3}
--- 混合参数 ---
位置参数: (1, 2)
关键字参数: {'x': 10, 'y': 20}
和: 3
Python使用LEGB规则来查找变量,代表四个层级:
函数内部 - 全局变量: 我是全局变量
函数内部 - 局部变量: 我是局部变量
函数外部 - 全局变量: 我是全局变量
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
#需要传入的参数,期数以及每期的现金流,单位为元。
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元
上面的PV函数综合运用了多个知识点:
*NCF可变参数:接收任意数量的现金流for循环遍历:逐期计算折现值pow()幂函数:计算 \((1+R)^n\)round()四舍五入:保留2位小数pv += ... 将各期折现值累加\[\large PV = \sum_{n=1}^{N} \frac{CF_n}{(1+R)^n}\]
| 原则 | 说明 |
|---|---|
| 避免全局变量 | 使用参数传递数据,降低耦合度 |
| 局部变量优先 | 限制变量的作用范围 |
| 常量大写命名 | 全局常量用 UPPER_CASE |
| 慎用global | 如必须修改全局变量,明确声明 |
函数设计三原则:
参数传递选择:
[商业大数据分析与应用]