在函数内修改全局变量
直接赋值会创建局部变量,而非修改全局变量:
count = 0
def wrong_increment():
count += 1 # UnboundLocalError!
# wrong_increment()
使用 global 关键字声明:
count = 0
def increment():
global count # 声明使用全局变量
count += 1
print(count)
increment() # 1
increment() # 2
print(count) # 2
闭包作用域(Enclosing)
嵌套函数中,内层函数可以访问外层函数的变量:可以访问,但是不能修改外层的
def outer():
x = "outer" # 外层函数的局部变量
def inner():
print(x) # 访问外层变量
inner()
outer() # outer
报错
def outer():
x = "outer" # 外层函数的局部变量
def inner():
x=x+"inner"
print(x) # 访问外层变量
inner()
outer() # outer
使用 nonlocal 关键字:
def make_counter():
count = 0
def increment():
nonlocal count # 声明使用外层变量
count += 1
return count
return increment
counter = make_counter()
print(counter()) # 1
print(counter()) # 2
print(counter()) # 3
nonlocal vs global:
关键字 作用 global 声明变量来自全局作用域 nonlocal 声明变量来自外层函数作用域
常见错误
错误 1:在函数内同时读写全局变量
x = 10
def demo():
print(x) # 先读
x = 20 # 再写 → 编译期就判定 x 是局部变量!
# demo() # UnboundLocalError
原因: Python 在编译函数时就确定了变量作用域,一旦函数内有赋值语句,该变量就被视为局部变量。
修正:
x = 10
def demo():
global x
print(x)
x = 20
demo() # 10
print(x) # 20
错误 2:默认参数的陷阱
def add_item(item, items=[]):
items.append(item)
return items
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] —— 意外!列表被共享了
默认参数在函数定义时求值,只创建一次。
修正:
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
闭包计数器
实现一个函数 make_multiplier(n),返回一个函数。返回的函数接收一个参数 x,返回 n * x。
要求使用闭包实现,不要使用 global。
def make_multiplier(x):
def multiplier(n):
return x * n
return multiplier
triple = make_multiplier(3)
print(triple(5)) # 15
print(triple(10)) # 30
double = make_multiplier(2)
print(double(7)) # 14
实现一个函数 create_account(initial_balance),返回两个字典:
deposit(amount): 存款,返回新余额withdraw(amount): 取款,余额不足返回"余额不足",否则返回新余额
要求使用闭包保存余额状态,不要暴露余额变量。
def create_account(initial_balance):
def deposit(amount):
nonlocal initial_balance
initial_balance += amount
return initial_balance
def withdraw(amount):
nonlocal initial_balance
if amount > initial_balance:
return "余额不足"
else:
initial_balance -= amount
return initial_balance
return deposit, withdraw
deposit, withdraw = create_account(100)
print(deposit(50)) # 150
print(withdraw(30)) # 120
print(withdraw(200)) # 余额不足




