把一段本事打包起来
同一段逻辑写三遍,改的时候要改三处,必然漏掉一处。函数就是"把这段话装进一个盒子,贴上名字,以后喊名字就行"。
def greet(name):
print(f"你好,{name}!")
greet("小明") # 你好,小明!
greet("小红") # 你好,小红!
拆解:
def—— 告诉 Python:"我要定义一个函数了"greet—— 函数名,命名规矩和变量一样(name)—— 参数,调用时传进来的材料的名字:和缩进 —— 和 if、for 一样,缩进的部分才是函数体
定义 ≠ 执行。 写完 def 那一段,函数只是被"记下来了",一行都不会跑。只有写 greet("小明") 调用它,里面的代码才真正执行。
return:把结果交回去
print 是显示给人看,return 是把值交回给调用者继续用。这两件事完全不同,新手极容易混。
def add(a, b):
return a + b
result = add(3, 5)
print(result) # 8
print(add(1, 2) * 10) # 30,返回值可以直接参与计算
如果 add 里写的是 print(a + b) 而不是 return,那么 result 会是 None——因为这个函数什么都没交回来。没写 return 的函数,返回值是 None。
return 一旦执行,函数立刻结束,后面的代码不再跑:
def check(age):
if age < 0:
return "年龄不能是负数"
return "正常"
这种"不合法就早点 return 出去"的写法叫卫语句,能让代码少嵌套好几层,非常值得养成习惯。
参数的几种玩法
def power(base, exp=2): # exp 有默认值
return base ** exp
print(power(3)) # 9 没传 exp,用默认的 2
print(power(3, 3)) # 27 传了就用传的
print(power(exp=3, base=2)) # 8,按名字传,顺序可以乱
带默认值的参数必须放在没默认值的后面,否则 Python 会报语法错误。
作用域:函数里的变量出不去
def f():
x = 10 # x 只在 f 内部存在
print(x)
f()
print(x) # NameError: name 'x' is not defined
函数内部是一个独立的小房间,里面新建的变量,出了门就消失。这是好事——它保证你写函数时不用担心撞名字。要把东西带出来,走 return 这个正门。
写好函数的三条准则
- 一个函数只做一件事。 名字里如果出现"并且",就该拆成两个。
- 名字用动词。
calculate_total、is_valid、load_data,一眼看出它干什么。 - 参数进,返回值出。 尽量不依赖外部变量,这样函数可以被单独测试、单独复用。
加个说明书
def bmi(weight, height):
"""计算 BMI 指数。weight 单位公斤,height 单位米。"""
return weight / (height ** 2)
三引号里的叫文档字符串(docstring)。写一句话说清"干什么、参数是什么单位",未来的你会省下大量猜测时间。
10 秒自测
def f(x):
x = x + 1
a = 5
f(a)
print(a)
a 是多少?答案是 5。函数里改的是它自己房间里的 x,没有 return,外面的 a 纹丝不动。