Python 变量赋值在函数中是如何工作的?

Python 变量赋值在函数中是如何工作的?,python,function,variables,variable-assignment,assign,Python,Function,Variables,Variable Assignment,Assign,当我在函数内部重新赋值变量时,它只在函数内部赋值。如果在函数外打印相同的变量,则该变量与未重新分配的变量相同 x = 5 #assigning x def sth(): x = 2 print(x) #output : 2 sth() #calling function print(x) #still output : 5 我想如果我调用函数,它会重新分配它,但它没有 我应该如何在函数内部重新赋值,使其也在函数外部重新赋值这

当我在函数内部重新赋值变量时,它只在函数内部赋值。如果在函数外打印相同的变量,则该变量与未重新分配的变量相同

x = 5      #assigning x

def sth():
    x = 2
    print(x)    #output : 2

sth()           #calling function
print(x)        #still output : 5
我想如果我调用函数,它会重新分配它,但它没有


我应该如何在函数内部重新赋值,使其也在函数外部重新赋值这是由于变量的作用域。您可以使用以下代码更改
x
的值

x=5#分配x
定义某物:
全球x
x=2
打印(x)#输出:2
sth()#调用函数
打印(x)#输出:2
但这不是执行赋值的好方法,正如@ggorlen在评论中所建议的那样,请确保您的函数在Python中是/

,如果没有
全局
关键字,您就不能在函数中重新赋值全局变量。但是,访问或修改全局变量是可以的

访问全局变量 当Python解释器在函数
print_x
中遇到
x
变量时,它首先在局部变量列表中查找它,然后在找不到它时,在全局变量列表中查找它并找到它的值,即5

修改全局变量 正如我所提到的,您可以修改全局变量,而无需执行任何特殊操作:

arr = []

def modify_arr():
    arr.append(5)

print(arr)  # prints [5]
类似地,当Python解释器读取
arr.append(5)
时,它在局部变量列表中查找变量
arr
,没有找到它,然后搜索全局变量列表,找到它并调用它的
append
方法

定义局部变量 当解释器看到
x=2
时,它会将一个名为
x
的变量添加到值为2的局部变量列表中。然后,当它遇到要在函数内部打印的
x
时,与之前一样,它首先在局部变量列表中查找
x
,因为它找到了它,所以只打印出2。因为它首先找到了一个本地的
x
,所以它从来没有找到全局的
x

函数调用后,
x
保持不变

在不使用global关键字的情况下重新分配和访问全局 这就是我必须纠正我在上一节中给出的一个解释的地方,这个解释并不是全部。我说“当解释器看到
x=2
时,它会在局部变量列表中添加一个名为
x
的变量”。但是如果这是真的,这个函数就不会崩溃,它应该只打印全局
x
,然后创建一个本地
x

然而,实际发生的情况是,在函数运行之前,所有局部变量名都已标识。因此,它在局部变量列表中存储了一个变量
x
,但该变量尚未赋值。因此,当它到达
print(x)
时,它会在局部变量列表中找到
x
,然后引发一个错误,因为它还没有被分配。函数中变量赋值的存在使该变量成为局部变量

使用global关键字重新分配和访问全局文件(正确的方式)
global
声明告诉解释器不应将
x
添加到局部变量列表中,即使它在函数中看到
x
的赋值。因此,所有更改都会更新全局列表中的
x

x
定义为
global
。函数有一个单独的名称空间,它有自己的变量。首先,不要对全局状态进行这种变异
x=2
是一种纯粹的本地分配。让你的功能。使用参数和返回值——这就是它们的用途!忽视这个建议将导致大量调试和重构的痛苦。我同意@ggorlen的观点。修改程序的设计要比把自己挖到更深的洞里好得多,因为“它是有效的”。@iammgt没关系,只要它不会导致堆栈溢出上出现大量重复或低质量的问题,你们都很好!:)很好的解释,但值得一提的是,假设您关心了解它的功能,那么这些事情都不应该在实际的程序中完成。事实证明,有缺陷的重新分配和打印(OP的原始代码)毕竟是最合理的行为。
arr = []

def modify_arr():
    arr.append(5)

print(arr)  # prints [5]
x = 5

def flawed_reassign_and_print_x():
    x = 2
    print(x)

flawed_reassign_and_print_x()  # prints 2
print(x)  # prints 5
x = 5

def very_flawed_print_and_reassign_x():
    print(x)
    x = 2

very_flawed_print_and_reassign_x()  # raises an exception!
x = 5

def change_and_print_x():
    global x

    x = 2
    print(x)

change_and_print_x()  # prints 2
print(x)  # prints 2