NOTE基于 Python 3。
定义函数 def
def greet(name): """向 name 问好。""" return f"Hello, {name}!"
print(greet("Alice"))print(greet.__name__) # greetdef 用于定义函数。函数体在调用时执行。函数可以作为变量、参数和返回值。
函数可以 return 多个值(实际返回一个元组),也可以没有 return(等价于 return None)。Defining Functions
参数
位置参数按定义顺序传入,也可以按名字传:greet(name="Alice")。带默认值的可以省略(Defining Functions):
def greet(name, greeting="Hello"): return f"{greeting}, {name}!"
print(greet("Alice"))print(greet("Bob", greeting="Hi"))默认值在定义时只求值一次。默认值不要使用可变对象([]、{}),多次调用会共享同一个对象:
def good(a, items=None): if items is None: items = [] items.append(a) return items*args 收集多余的位置参数为元组,**kwargs 收集多余的关键字参数为字典:
def demo(a, *args, **kwargs): print(a, args, kwargs)
demo(1, 2, 3, x=4) # 1 (2, 3) {'x': 4}print(*(1, 2, 3)) # 等同于 print(1, 2, 3)/ 之前的参数只能按位置传入(3.8+),* 之后的只能按关键字传入,例如 def f(pos, /, both, *, kwonly)。
return
return 结束当前函数调用,并返回表达式的值。没有表达式时返回 None。
def find_first(pred, items): for x in items: if pred(x): return x return Nonelambda
lambda 创建匿名函数,语法为 lambda 参数: 表达式。函数体只能是一个表达式。较复杂的逻辑使用 def。
pairs = [(2, "b"), (1, "a"), (3, "c")]pairs.sort(key=lambda p: p[0])命名空间与作用域
变量按 LEGB 顺序查找:Local(当前函数)、Enclosing(外层函数)、Global(模块全局)、Built-in(内置名,如 len)。命名与绑定
x = "global"
def outer(): x = "enclosing"
def inner(): x = "local" print(x) # local
inner() print(x) # enclosing
outer()print(x) # global函数定义时会捕获外层作用域(闭包)。内层函数可以读取外层变量;若要给外层非全局变量赋值,使用 nonlocal;给模块级变量赋值使用 global。
if / for / while / try 不会像函数那样创建局部作用域,块中赋值的变量在块外仍可使用。Naming and binding。
内置名在 builtins 模块:import builtins; dir(builtins)。
global 与 nonlocal
global 把本函数里的名字标成模块全局。nonlocal 标成最近一层外层函数里的名字(不能是全局)。
函数体内只要出现对某名字的赋值,整个函数都把它当局部。因此下面会 UnboundLocalError:
x = 1
def f(): print(x) # 想读全局 x x = 2 # 这一行让 x 在整个 f 里都是局部要改全局就写 global x,或不要在函数里给同名赋值。
count = 0
def inc_global(): global count count += 1
def make_counter(): n = 0
def inc(): nonlocal n n += 1 return n
return inc
c = make_counter()print(c(), c()) # 1, 2inc_global()print(count) # 1global 会让数据流难追踪;状态用参数、返回值或类封装。
try / except / else / finally
The try statement 与 Errors and Exceptions:
try: risky()except ValueError as e: handle(e)except (TypeError, OSError): recover()else: # 仅当 try 块未抛出异常时执行 on_success()finally: # 总是执行(除非进程被杀死等) cleanup()except:匹配异常类型(元组表示多个)。as e绑定异常实例;在 Python 3 里,except块结束后e会被删除,避免循环引用(PEP 3110)。else:没有异常时运行,常把可能抛错的逻辑放在try、成功路径放在else,避免把else里的错误当成except能处理的同一类问题。finally:用于释放资源;若有return,finally仍会在返回前执行。- 顺序:
try→ 若异常则匹配的except→ 无异常则else→ 始终finally。
raise 抛出异常:raise ValueError("msg");raise 单独使用则重新抛出当前异常(常在 except 里记录后再抛)。
def parse_int(s): try: return int(s) except ValueError: raise ValueError(f"不是整数: {s!r}") from None # 抑制异常链Exception chaining:内层 raise ... from e 保留原因;from None 隐藏上下文。
用户自定义异常:继承 Exception(不要直接继承 BaseException,除非做系统退出类异常)。
class MyAppError(Exception): passassert 用于断言。使用 -O 优化时会被忽略,不适合作为常规错误处理。
内置异常
下列名字来自 Built-in Exceptions。
| 异常 | 典型触发场景 |
|---|---|
Exception | 几乎所有用户可捕获异常的基类 |
StopIteration | 迭代器没有更多元素(next / for 结束) |
StopAsyncIteration | 异步迭代器结束 |
ArithmeticError | 算术错误分支的基类 |
FloatingPointError | 浮点运算失败(极少见,依赖平台) |
OverflowError | 数值结果太大 |
ZeroDivisionError | 除法或取模除零 |
AssertionError | assert 失败 |
AttributeError | 属性不存在或无法设置 |
EOFError | input() 在无数据可读时(如 Ctrl+D) |
ImportError | import 失败 |
ModuleNotFoundError | 找不到模块(ImportError 子类) |
LookupError | 索引/键错误的基类 |
IndexError | 序列下标越界 |
KeyError | 字典键不存在 |
MemoryError | 内存不足 |
NameError | 未定义的名字 |
UnboundLocalError | 局部名字在赋值前被引用 |
OSError | 系统 / I/O 相关(IOError 是其别名) |
FileNotFoundError | 文件不存在 |
PermissionError | 权限不足 |
RecursionError | 超过最大递归深度 |
ReferenceError | 弱引用对象已销毁(少见) |
RuntimeError | 一般不落在更具体类型时的运行时错误 |
NotImplementedError | 抽象方法 / 待实现 |
SyntaxError | 语法错误(编译期) |
IndentationError | 缩进错误 |
TabError | Tab 与空格混用 |
SystemError | 解释器内部错误 |
TypeError | 类型不对或参数个数不对 |
ValueError | 类型对但值不合法(如 int("abc")) |
UnicodeError | Unicode 编解码相关基类 |
UnicodeDecodeError / UnicodeEncodeError | 解码 / 编码失败 |
Warning | 警告类别基类(不是 Exception 同级习惯捕获对象) |
一般不捕获 BaseException 下的 KeyboardInterrupt、SystemExit、GeneratorExit,除非在做框架级顶层处理。
with 与上下文管理器
with 语句用于管理资源:进入时 setup,离开时 teardown,即使发生异常也会清理。PEP 343 定义协议。
上下文管理器需实现:
__enter__(self):进入with块前调用;返回值绑定到as后的变量(若无as则忽略返回值)。__exit__(self, exc_type, exc_val, exc_tb):离开with块时调用。若返回真值,会抑制当前异常(一般不这么做);否则异常继续传播。
class Tag: def __init__(self, name): self.name = name
def __enter__(self): print(f"<{self.name}>") return self
def __exit__(self, exc_type, exc, tb): print(f"</{self.name}>") return False
with Tag("p") as t: print("body")内置 open() 返回的文件对象、threading.Lock 等已实现该协议。自定义资源管理可用 contextlib.contextmanager 装饰生成器,或用 contextlib.AbstractContextManager。多个上下文管理器可写 with A() as a, B() as b:。
iter 与 next
迭代器实现迭代器协议:__iter__() 返回自身(或另一迭代器),该对象再提供 __next__()。内置 iter() 优先调用 __iter__();若没有 __iter__ 但实现了从 0 开始的 __getitem__,仍可按序列方式迭代(见 iterator protocol)。自定义可迭代对象时,实现 __iter__ 即可。
next(iterator[, default]) 调用 iterator.__next__()。没有更多元素时,__next__() 抛出 StopIteration;若提供了 default,则返回 default 而不抛异常。
容器(如 list)本身通常不是迭代器,但可迭代(iterable):__iter__() 返回一个新的迭代器。每次 for x in lst: 都会先 iter(lst) 再反复 next。
it = iter([10, 20, 30])print(next(it)) # 10print(next(it)) # 20print(next(it, "没了")) # 30print(next(it, "没了")) # 没了for 循环在底层等价于:取迭代器 → 反复 next → 捕获 StopIteration 结束。实现 __iter__ 与 __next__:
class CountDown: def __init__(self, n): self.n = n
def __iter__(self): return self
def __next__(self): if self.n <= 0: raise StopIteration self.n -= 1 return self.n + 1生成器与 yield
生成器是一种迭代器,由含 yield 的函数或 yield from 表达式产生。调用生成器函数不会立刻执行函数体,而是返回一个生成器对象;每次 next() 或 for 循环驱动执行到下一个 yield,产出值并暂停。
def count_up_to(n): i = 1 while i <= n: yield i i += 1
for x in count_up_to(3): print(x) # 1, 2, 3生成器表达式 (x * x for x in range(5)) 语法类似列表推导,但结果是生成器而非列表,适合大数据或流水线。Generator expressions。
yield from iterable 把产出委托给另一个可迭代对象,常用于扁平化嵌套生成器。要用 with 包一层生成器,需 contextlib.contextmanager;生成器本身不是上下文管理器。
装饰器
PEP 318 引入函数装饰器语法:@decorator 放在 def(或 class)前,等价于 func = decorator(func)。装饰器通常是接受 callable、返回 callable 的可调用对象。
def log_calls(fn): def wrapper(*args, **kwargs): print(f"calling {fn.__name__}") return fn(*args, **kwargs) return wrapper
@log_callsdef add(a, b): return a + b
add(1, 2) # 先打印 calling add,再返回 3被包装后 wrapper.__name__ 等元数据会丢;用 functools.wraps 拷回去:
import functools
def log_calls(fn): @functools.wraps(fn) def wrapper(*args, **kwargs): print(f"calling {fn.__name__}") return fn(*args, **kwargs) return wrapper带参装饰器:外层函数先接收装饰器参数,返回真正的装饰器。
def repeat(times): def decorator(fn): def wrapper(*args, **kwargs): for _ in range(times): result = fn(*args, **kwargs) return result return wrapper return decorator
@repeat(3)def hi(): print("hi")类也可以当装饰器(实现 __call__)。内置装饰器如 staticmethod、classmethod、property。装饰器栈从下往上应用:@a @b def f 等价于 f = a(b(f))。
附录:内置异常继承关系
Exception hierarchy。缩进表示子类。
| 基类 | 直接子类 |
|---|---|
BaseException | SystemExit, KeyboardInterrupt, GeneratorExit, Exception |
Exception | StopIteration, StopAsyncIteration, ArithmeticError, AssertionError, AttributeError, BufferError, EOFError, ImportError, LookupError, MemoryError, NameError, OSError, ReferenceError, RuntimeError, SyntaxError, SystemError, TypeError, ValueError, Warning |
ArithmeticError | FloatingPointError, OverflowError, ZeroDivisionError |
LookupError | IndexError, KeyError |
OSError | BlockingIOError, ChildProcessError, ConnectionError, FileExistsError, FileNotFoundError, InterruptedError, IsADirectoryError, NotADirectoryError, PermissionError, ProcessLookupError, TimeoutError … |
ConnectionError | BrokenPipeError, ConnectionAbortedError, ConnectionRefusedError, ConnectionResetError |
ImportError | ModuleNotFoundError |
NameError | UnboundLocalError |
RuntimeError | NotImplementedError, RecursionError |
SyntaxError | IndentationError → TabError |
UnicodeError | UnicodeDecodeError, UnicodeEncodeError, UnicodeTranslateError |
ValueError | UnicodeError 等 |
except OSError 可捕 FileNotFoundError;except LookupError 可捕 IndexError 与 KeyError。
附录:函数参数汇总
| 写法 | 含义 |
|---|---|
def f(a, b) | 位置或关键字 |
def f(a, b=0) | b 有默认值 |
def f(a, /, b) | a 仅位置(3.8+) |
def f(a, *, b) | b 仅关键字 |
def f(*args) | 多余位置 → 元组 |
def f(**kwargs) | 多余关键字 → 字典 |
def f(a, /, b, *args, c=1, **kw) | 顺序:仅位置、/、位置或关键字、*args、仅关键字、**kwargs |
参考
官方文档(中文版):
- More Control Flow Tools — Defining Functions — 默认参数、关键字参数、
*args/**kwargs、Docstring - More Control Flow Tools — Intermezzo: Coding Style — 命名与可读性
- Errors and Exceptions — 异常处理、
else/finally、raise、用户异常、异常链 - Compound statements — Function definitions — 完整参数语法、
lambda不能替代def的全部能力 - Compound statements — The try statement —
try/except/else/finally语义 - Compound statements — The with statement —
with与as - Data model — With Statement Context Managers —
__enter__/__exit__ - Glossary — iterator / generator / iterable — 术语定义
- Execution model — Naming and binding — LEGB、闭包
- Simple statements — global / nonlocal / return / raise / yield
- Built-in Exceptions — 异常列表与继承树
- functools.wraps — 装饰器保留元数据
- contextlib — 上下文管理器工具
PEP:
- PEP 318 — Decorators for Functions and Methods
- PEP 343 — The “with” Statement
- PEP 3102 — Keyword-Only Arguments
- PEP 3110 — Catching exceptions in Python 3000
菜鸟教程:
- 菜鸟教程 · Python3 函数
- 菜鸟教程 · Python3 迭代器与生成器
- 菜鸟教程 · Python3 装饰器
- 菜鸟教程 · Python3 错误和异常
- 菜鸟教程 · Python3 命名空间/作用域
- 菜鸟教程 · Python3 with
- 菜鸟教程 · Python3 lambda