,

python 作用域注意事项

在函数内修改全局变量 直接赋值会创建局部变量,而非修改全局变量: 使用 global 关键字声明: 闭包作用域…

在函数内修改全局变量

直接赋值会创建局部变量,而非修改全局变量:

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))  # 余额不足

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

About the Author

每个人都有自己得时区,在自己得时区里,一切都是准时的。

BlockSpare — News, Magazine and Blog Addons for (Gutenberg) Block Editor