python 中参数变量的范围是什么?
What is the scope of argument variables in python?
考虑以下情况:
案例 1:
def fun(arg):
arg += 1
my_var = 1
fun(my_var)
print(my_var)
>> 1
案例 2:
def fun(arg):
arg += [4]
my_var = [1,2,3]
fun(my_var)
print(my_var)
>> [1, 2, 3, 4]
案例 3:
def fun(arg):
arg = arg + [4]
my_var = [1,2,3]
fun(my_var)
print(my_var)
>> [1, 2, 3]
案例 4:
def fun(arg):
print(arg)
fun("Hi")
print(arg)
>> Hi
Traceback (most recent call last):
File "<string>", line 8, in <module>
NameError: name 'arg' is not defined
案例 4 表明参数变量的范围在函数内。案例 1 和案例 3 支持,因为对函数内 arg 变量的更改不会反映在全局参数中。
但是为什么会发生第二种情况呢?当我使用 append 而不是 += 时,我注意到了同样的事情。发生在 arg 上的更改不应该对从不同范围调用函数的变量产生任何影响吗?
感谢任何帮助。提前致谢。
答案很简单:函数参数是局部变量!
更多观察:
=
是赋值运算符并重新绑定一个变量。这将永远不会改变对象(ecxeption 切片分配)。
+=
是它自己的运算符,并作为可变类型的突变实现。您可以通过实现 __iadd__
dunder 方法为您自己的类型实现它的行为。
因此,一般来说,a = a + b
不 等同于 a += b
!
对于列表,a += b
对应于 a.extend(b)
。另一方面,a + b
创建一个 new 列表对象,a = a + b
将变量 a
重新绑定到该新对象。
案例 2 是唯一一个在实例上使用变异方法的案例。这会影响传递的参数。
其他人什么也不做,或者只是重新分配参数。 python 中的赋值仅影响被赋值的变量,而不影响仍引用前一个实例的其他变量。
强制性 link 到 Ned Batchelder
Python 让您可以简单地通过为变量赋值来创建变量,而无需预先声明变量。分配给变量的值决定了变量类型。
如果你在每个函数上打印变量类型,你就会看到它。
#case 2
def fun2(arg2):
arg2 += [4]
my_var2 = [1,2,3]
#fun(my_var2)
print(type(my_var2))
print(type(my_var2[0]))
#case 4 where no type assigned
def fun4(arg44):
print(arg)
#fun(myvar4)
print(arg4)
在函数内声明的任何变量都是局部的,但列表和字典的行为有点不同。即使不写 global list_name
也可以将元素附加到列表
在函数内部也不会将列表作为参数传递给函数。只有 lists 和 dict 是这样的。然而,案例 2 和案例 3 的差异似乎是一个错误。好像写的时候
a = [1,2,3]
def fun(a_list):
a_list = a_list + [4]
print(a_list)
fun(a)
>>>[1,2,3,4]
你得到 [1,2,3,4],所以它变成局部变量,但是当你写 arg += [4]
时,它表现为全局变量
考虑以下情况:
案例 1:
def fun(arg):
arg += 1
my_var = 1
fun(my_var)
print(my_var)
>> 1
案例 2:
def fun(arg):
arg += [4]
my_var = [1,2,3]
fun(my_var)
print(my_var)
>> [1, 2, 3, 4]
案例 3:
def fun(arg):
arg = arg + [4]
my_var = [1,2,3]
fun(my_var)
print(my_var)
>> [1, 2, 3]
案例 4:
def fun(arg):
print(arg)
fun("Hi")
print(arg)
>> Hi
Traceback (most recent call last):
File "<string>", line 8, in <module>
NameError: name 'arg' is not defined
案例 4 表明参数变量的范围在函数内。案例 1 和案例 3 支持,因为对函数内 arg 变量的更改不会反映在全局参数中。
但是为什么会发生第二种情况呢?当我使用 append 而不是 += 时,我注意到了同样的事情。发生在 arg 上的更改不应该对从不同范围调用函数的变量产生任何影响吗?
感谢任何帮助。提前致谢。
答案很简单:函数参数是局部变量!
更多观察:
=
是赋值运算符并重新绑定一个变量。这将永远不会改变对象(ecxeption 切片分配)。
+=
是它自己的运算符,并作为可变类型的突变实现。您可以通过实现 __iadd__
dunder 方法为您自己的类型实现它的行为。
因此,一般来说,a = a + b
不 等同于 a += b
!
对于列表,a += b
对应于 a.extend(b)
。另一方面,a + b
创建一个 new 列表对象,a = a + b
将变量 a
重新绑定到该新对象。
案例 2 是唯一一个在实例上使用变异方法的案例。这会影响传递的参数。
其他人什么也不做,或者只是重新分配参数。 python 中的赋值仅影响被赋值的变量,而不影响仍引用前一个实例的其他变量。
强制性 link 到 Ned Batchelder
Python 让您可以简单地通过为变量赋值来创建变量,而无需预先声明变量。分配给变量的值决定了变量类型。
如果你在每个函数上打印变量类型,你就会看到它。
#case 2
def fun2(arg2):
arg2 += [4]
my_var2 = [1,2,3]
#fun(my_var2)
print(type(my_var2))
print(type(my_var2[0]))
#case 4 where no type assigned
def fun4(arg44):
print(arg)
#fun(myvar4)
print(arg4)
在函数内声明的任何变量都是局部的,但列表和字典的行为有点不同。即使不写 global list_name
也可以将元素附加到列表
在函数内部也不会将列表作为参数传递给函数。只有 lists 和 dict 是这样的。然而,案例 2 和案例 3 的差异似乎是一个错误。好像写的时候
a = [1,2,3]
def fun(a_list):
a_list = a_list + [4]
print(a_list)
fun(a)
>>>[1,2,3,4]
你得到 [1,2,3,4],所以它变成局部变量,但是当你写 arg += [4]
时,它表现为全局变量