你以为在Python中调用一个变量就像在房间里找东西?不妨看看这个令人抓狂的例子:
x = 10
def outer():
x = 20
def inner():
print(x) # 这个x到底是谁?
return inner
func = outer()
func() # 输出什么?
这不是普通的变量查找,而是一场精心设计的捉迷藏游戏。今天我们将化身代码侦探,破解Python世界的三大空间谜案。
一、变量查找的密室逃脱
Python变量查找遵循LEGB法则,像侦探破案一样逐层搜索:
-
Local(本地):案发第一现场
-
Enclosing(闭包):隔壁房间
-
Global(全局):整栋大楼
-
Built-in(内置):城市基础设施
def crime_scene():
clue = "指纹"
def suspect_room():
clue = "凶器"
def murder_spot():
print(clue) # 找到哪个clue?
return murder_spot
return suspect_room()
detective = crime_scene()
detective() # 输出"凶器"
破解技巧:使用global和nonlocal声明能突破搜索层级(但要慎用!)
二、闭包:会记忆的函数
闭包就像携带记忆胶囊的函数,即使离开案发现场也能记住关键证据:
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
c1 = make_counter()
print(c1(), c1(), c1()) # 1 2 3
c2 = make_counter()
print(c2()) # 1
致命陷阱:在循环中创建闭包
functions = []
for i in range(3):
def show():
print(i)
functions.append(show)
for f in functions:
f() # 全输出2!为什么?
修复方案:用参数捕获当前值
for i in range(3):
def wrapper(x):
def show():
print(x)
return show
functions.append(wrapper(i))
三、装饰器:代码的变形金刚
装饰器实质是语法糖衣下的闭包操作:
def debugger(func):
def wrapper(*args):
print(f"🔍 正在调用 {func.__name__},参数:{args}")
result = func(*args)
print(f"✅ 调用完成,结果:{result}")
return result
return wrapper
@debugger
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(4))
输出结果:
🔍 正在调用 fibonacci,参数:(4)
🔍 正在调用 fibonacci,参数:(3)
...(递归调用跟踪)
✅ 调用完成,结果:3
高阶玩法:带参数的装饰器
def retry(max_attempts):
def decorator(func):
def wrapper(*args):
attempts = 0
while attempts < max_attempts:
try:
return func(*args)
except Exception:
attempts += 1
print(f"重试第{attempts}次...")
raise Exception("超出最大重试次数")
return wrapper
return decorator
@retry(3)
def unstable_api():
import random
if random.random() < 0.7:
raise ConnectionError
return "成功"
四、命名空间的量子纠缠
用globals()和locals()可以窥探Python的变量平行宇宙:
def quantum_physics():
earth = "🌍"
print(locals()) # {'earth': '🌍'}
def parallel_world():
mars = "♂️"
print(locals()) # {'mars': '♂️'}
parallel_world()
print(globals().keys()) # 显示全局命名空间
quantum_physics()
危险实验:动态修改命名空间
def create_variable():
globals()["black_magic"] = "🔮"
create_variable()
print(black_magic) # 输出🔮(但千万别在生产环境这么做!)
五、实战生存手册
避免变量污染全局空间:
# 错误示范
cache = {} # 全局变量易被篡改
# 正确做法
def create_cache():
_cache = {}
def get(key):
return _cache.get(key)
def set(key, value):
_cache[key] = value
return get, set
装饰器工厂模式:
def register_route(methods=['GET']):
def decorator(func):
func.__route_methods__ = methods
return func
return decorator
@register_route(methods=['GET', 'POST'])
def user_profile():
return "用户页面"
闭包实现私有变量:
def create_account(initial):
balance = initial
def deposit(amount):
nonlocal balance
balance += amount
def withdraw(amount):
nonlocal balance
if amount > balance:
raise ValueError
balance -= amount
def get_balance():
return balance
return deposit, withdraw, get_balance
dep, wd, check = create_account(1000)
当你在Python中写下def时,实际上是在创造一个新的宇宙。每个函数都是一个携带独立时空的胶囊,闭包是它的记忆芯片,装饰器是它的变形装甲。下期我们将闯入元类的四次元空间,探索类创建的量子领域。
442



被折叠的 条评论
为什么被折叠?



