if
/ while
/ for
内部——语法完全合法;def
,都会新建一个函数对象(旧的会被垃圾回收,除非外部还有引用);1. 分支里定义——“按需生成”
debug = True
if debug:
def foo(x): # 只有 debug=True 时 foo 才存在
print('debug:', x)
else:
foo = lambda x: None # 生产环境给个空壳
foo(123) # 如果 debug=False 且 else 分支没有 foo = ...,这里 NameError
2. 循环里定义——“闭包陷阱”经典现场
funcs = []
for i in range(3):
def f(): # 每轮都新建一个函数对象
return i # 闭包绑定的是“变量 i”而不是“值 i”
funcs.append(f)
print([g() for g in funcs]) # [2, 2, 2] 不是 [0, 1, 2]
for i in range(3):
def f(_i=i): # 默认参数在定义时求值
return _i
funcs.append(f)
3. 函数内部再定义——“工厂函数”模式
def make_adder(n):
def adder(x): # 每次调用 make_adder 都新建一个 adder
return x + n
return adder
add5 = make_adder(5)
print(add5(7)) # 12
def
”可以方便地生成携带不同环境的闭包。4. 类定义体里玩分支——实现“条件方法”
import sys
class Logger:
if sys.stderr.isatty(): # 终端才给彩色
def _log(self, msg):
print(f'\033[31m{msg}\033[0m', file=sys.stderr)
else: # 重定向到文件就去掉颜色
def _log(self, msg):
print(msg, file=sys.stderr)
def
同样合法。结论速记