Python函数未传参也未声明global,为何能访问外部字典resources?
关于Python函数修改全局字典的疑问解答
问题背景
我正在学习Angela的《Python100天》课程第15天,之前的认知是函数无法访问外部变量,除非将其作为参数传入或在函数内声明global关键字。但看到示例代码中的make_coffee函数,既未将外部全局字典resources作为参数传入,也未声明global,却能直接修改它;而我自己编写的use_resources函数是通过传参来操作资源字典的。想请教该现象的原理是什么?
相关代码片段
Angela的make_coffee函数
def make_coffee(drink_name, order_ingredients): """Deduct the required ingredients from the resources.""" for item in order_ingredients: resources[item] -= order_ingredients[item] print(f"Here is your {drink_name} ☕️. Enjoy!")
我编写的use_resources函数
def use_resources(user_order, machine_menu, machine_resources): """Deduct the resources needed for the user's order and returns the current resources of the machine after the user's order. """ for menu_ingredients_key in machine_menu[user_order]["ingredients"]: for resources_key in machine_resources: if resources_key == menu_ingredients_key: machine_resources[menu_ingredients_key] -= menu[user_order]["ingredients"][menu_ingredients_key] print(f"Here is your {user_order} ☕. Enjoy! Come again :)")
原理解析
这本质是Python对可变对象和不可变对象的访问规则差异:
- 全局变量如果是可变对象(比如字典、列表),函数内部不需要声明
global,就可以直接修改它的内部元素(比如字典的键值对、列表的元素)。因为你没有重新给这个全局变量赋值,只是修改了它指向的内存空间里的内容。 - 如果是不可变对象(比如整数、字符串、元组),函数内部要修改它的话,要么传参,要么声明
global——因为不可变对象无法直接修改内部内容,只能重新赋值,这时候就会被视为创建局部变量,必须用global声明才能操作全局的那个变量。
回到你的例子:
- Angela的
make_coffee函数里,resources是全局字典(可变对象),函数只是修改了它的键对应的值,没有重新给resources赋值(比如没有写resources = {}这种代码),所以不需要global就能生效。 - 你写的
use_resources函数是把资源字典作为参数传入,这其实是传递了字典的引用,函数内修改字典的元素同样会影响外部的原字典,和直接操作全局字典的本质逻辑一致,只是多了一层参数传递的过程。
内容的提问来源于stack exchange,提问作者Kejer
相关产品推荐
相关产品推荐

