4
函数:把动作打包成按钮
Functions, Parameters & Scope
函数就是"起个名字的一段代码"。你给它原料(参数),它还给你成品(返回值)。写函数的好处:一次写好,到处调用;改的时候只改一处。别在主程序里堆三千行——拆成函数,世界清净。
定义与参数:六种传参姿势
# 最基础的函数
def greet(name):
"""打个招呼(文档字符串,三引号包起来)"""
return f"你好,{name}!"
print(greet("小明")) # 你好,小明!
# ① 位置参数:按顺序传
# ② 默认参数:调用时不传就用默认值
def greet(name, greeting="你好"):
return f"{greeting},{name}!"
print(greet("小红")) # 你好,小红!
print(greet("小红", "早上好")) # 早上好,小红!
# ③ 可变参数 *args:收一堆位置参数,打包成元组
def sum_all(*nums):
return sum(nums)
print(sum_all(1, 2, 3, 4)) # 10
# ④ 关键字参数 **kwargs:收一堆命名参数,打包成字典
def print_info(**info):
for k, v in info.items():
print(f"{k}: {v}")
print_info(name="小明", age=18, city="南京")
# ⑤ 仅限关键字参数:* 后面的参数必须用名字传
def create_user(name, *, active=True):
print(name, active)
# create_user("小明", False) # 报错!必须写 active=False
create_user("小明", active=False) # 正确
# ⑥ 仅限位置参数:/ 前面的参数只能按位置传,不能用名字
def f(x, y, /, z):
return x + y + z
print(f(1, 2, z=3)) # 6
# f(x=1, y=2, z=3) # 报错,x、y 不能用名字传
作用域:LEGB 规则
规名字在哪里能被找到
Python 找一个变量时,按这个顺序层层往外找:Local(当前函数内)→ Enclosing(外层函数)→ Global(模块顶层)→ Built-in(内置的,比如 print、len)。找到哪层用哪层,找不到就报 NameError。函数内部默认不能改外面的变量——想改要加 global(全局)或 nonlocal(外层)关键字,新手别乱用。
x = 10 # 全局
def f():
x = 20 # 这只是函数内部的局部 x,不影响外面
print("函数里:", x)
f()
print("外面:", x) # 外面: 10
# 想在函数里改全局变量?加 global
count = 0
def inc():
global count
count += 1
lambda 与高阶函数
# lambda:匿名小函数,一行写完,适合临时用一下
square = lambda x: x * x
print(square(5)) # 25
# 高阶函数:把函数当参数传
nums = [3, 1, 4, 1, 5, 9]
# map:对每个元素加工
print(list(map(lambda x: x*2, nums)))
# [6, 2, 8, 2, 10, 18]
# filter:筛选
print(list(filter(lambda x: x % 2 == 0, nums)))
# [4]
# sorted 的 key:按什么规则排,最常用!
users = [{"name": "小明", "age": 18},
{"name": "小红", "age": 22}]
by_age = sorted(users, key=lambda u: u["age"])
print(by_age[0]["name"]) # 小明(年纪小的排前面)
函数注解(Python 3.5+)只是给人和工具看的提示,不强制检查类型:
def add(a: int, b: int) -> int:
return a + b
# add(1, "x") # 运行时照样能跑,只是 IDE 会黄线警告你