系列文章
Python 从入门到精通
第 7 / 12 篇
从环境安装和基础语法出发,逐步学习工程实践、自动化、数据处理与 Web 开发。
-
01
Python 怎么装、怎么用 -
02
变量、数字和字符串 -
03
列表:把一组数据放在一起 -
04
元组、集合和字典 -
05
条件判断:让程序做选择 -
06
循环:重复的事交给程序 -
07
函数:把代码整理成可复用的块正在阅读 -
08
模块与包:拆分你的程序 -
09
输入、输出与字符串格式化 -
10
文件读写:保存程序的数据 -
11
异常处理:程序出错时怎么办 -
12
基础阶段练习:命令行记账本
写了这么多行代码,你可能已经发现一个问题:同样的逻辑(比如”算平均分”)要在好几个地方用,就得复制粘贴好几遍。复制粘贴一时爽,改需求火葬场——改一处漏一处。解决之道就是函数:把一段代码打包,起个名字,随用随调。
定义和调用
def greet(name):
print(f"你好,{name}!")
greet("小明") # 你好,小明!
greet("小红") # 你好,小红!
def 定义函数,后面跟函数名和括号,冒号下面是函数体(记得缩进)。函数不调用就不会执行,调用就写函数名加括号。
参数:函数的数据入口
函数可以接收参数,参数在括号里声明:
def add(a, b):
return a + b
print(add(3, 5)) # 8(位置参数)
print(add(a=1, b=2)) # 3(关键字参数,更明确)
参数可以带默认值,调用时可以省略:
def greet(name, greeting="你好"):
print(f"{greeting},{name}!")
greet("小明") # 你好,小明!
greet("小红", "早上好") # 早上好,小红!
注意规则:默认值参数必须放在非默认参数后面。写成 def f(a=1, b) 会报语法错误。
return:函数的输出
函数处理完数据,用 return 把结果交回去:
def average(scores):
return sum(scores) / len(scores)
avg = average([92, 85, 78, 100])
print(f"平均分:{avg:.1f}") # 平均分:88.8
几个要点:
return后面的代码不会执行,函数到 return 就结束了- 没有 return 的函数返回
None(比如只打印的函数) - 可以返回多个值,用逗号分隔,本质是返回元组:
return a, b
def min_max(nums):
return min(nums), max(nums)
lo, hi = min_max([3, 1, 4, 1, 5])
print(lo, hi) # 1 5(解包接收多返回值)
*args 和 **kwargs:不确定多少个参数
有时候不知道调用方会传几个参数,用 *args 收位置参数(打包成元组)、**kwargs 收关键字参数(打包成字典):
def log(level, *messages):
for msg in messages:
print(f"[{level}] {msg}")
log("INFO", "启动", "加载配置", "连接数据库")
# [INFO] 启动
# [INFO] 加载配置
# [INFO] 连接数据库
def show_info(**info):
for key, value in info.items():
print(f"{key}: {value}")
show_info(name="南山", year=2026)
# name: 南山
# year: 2026
名字 args/kwargs 是约定俗成,星号才是关键。
作用域:函数里的变量是”本地人”
x = 10 # 全局变量
def change():
x = 20 # 这是新的局部变量,和外面的 x 无关!
print(x) # 20
change()
print(x) # 10(外面的没变)
函数里赋值默认创建局部变量,函数结束就销毁。想改全局变量要用 global 声明,但尽量别用——全局变量多了,程序的状态就难追踪了。正确做法是把值传进函数、用 return 传出来:
def add_one(x):
return x + 1
x = 10
x = add_one(x) # 显式更新
print(x) # 11
文档字符串:给函数写说明书
def area(radius):
"""计算圆的面积。
参数 radius: 半径(数字)
返回: 面积
"""
return 3.14159 * radius ** 2
print(area.__doc__) # 能看到说明
help(area) # 交互环境里也能看
函数第一行的三引号字符串就是文档字符串,好的习惯从第一篇就养成。
新手坑
坑 1:忘记 return。函数算完没 return,外面拿到的是 None,再往下算就报错:TypeError: unsupported operand type(s)。
坑 2:默认参数用可变对象。
def add_item(item, items=[]): # 危险!默认列表只创建一次
items.append(item)
return items
print(add_item("a")) # ['a']
print(add_item("b")) # ['a', 'b'] ??上次的还在!
默认参数在定义时只创建一次,之后每次调用都复用。要安全就用 None:
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
坑 3:函数名和变量名冲突。后面定义的同名变量会覆盖函数,调用的就是变量了。
小结
def 函数名(参数):定义,函数名 + 括号调用- 参数支持默认值(放后面)、
*args、**kwargs return返回结果(可多值),没有 return 返回 None- 函数内变量默认是局部的;少用 global,多用传参 + return
- 写文档字符串;默认参数别用可变对象
练习
- 写一个函数
fahrenheit(c),把摄氏温度转成华氏(公式:F = C × 9/5 + 32) - 写一个函数
count_chars(s),统计字符串里每个字符出现次数,返回字典 - 思考:下面的代码输出什么,为什么?
def f(): return 1 print("这行会执行吗?") print(f())