我认为我很了解Python变量范围,但是今天我遇到了这个代码。
from __future__ import print_function
def main():
v_Matrix =[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
print(v_Matrix)
print()
f_Rotate(v_Matrix)
print(v_Matrix)
hh = 3
f_This(hh)
print(hh)
def f_Swap(v_Matrix, r1, c1, r2, c2):
v_Matrix[r1][c1], v_Matrix[r2][c2] = v_Matrix[r2][c2], v_Matrix[r1][c1]
def f_Transpose(v_Matrix):
for row in range(len(v_Matrix)):
for col in range(row):
f_Swap(v_Matrix, row, col, col, row)
def f_FlipVertical(v_Matrix):
v_Size = len(v_Matrix)
for row in range(v_Size // 2):
for col in range(v_Size):
f_Swap(v_Matrix, row, col, v_Size - row - 1, col)
def f_Rotate(v_Matrix):
f_Transpose(v_Matrix)
f_FlipVertical(v_Matrix)
def f_This(hh):
hh = hh * 2
if __name__ == '__main__':
main()
运行时,变量v_Matrix
似乎表现得像全局一样。但是,测试变量hh
的行为符合预期,其中一个范围位于main()
,另一个范围位于f_This
。
v_Matrix
不是全局的,在各种函数中被修改,但不在这些函数之间来回传递,甚至返回main()
。然而,在v_Matrix
范围内可以访问这些函数中应用于main()
的值更改,如输出之间所示。但是,正如预期的那样,测试变量hh
的值在main()
范围内不会发生变化,只会在函数范围内发生变化。
是什么给出了?
答案 0 :(得分:2)
Python中的所有东西都是一个对象,无论它们是可变的还是不可变的,对象都以相同的方式传递给函数。但是,可以在函数外部看到对可变对象的更改。
示例:
def f(c,d):
print('Inside f()')
print(' id(a) =',id(a),'value =',a)
print(' id(b) =',id(b),'value =',b)
print(' id(c) =',id(c),'value =',c)
print(' id(d) =',id(d),'value =',d)
c = 4 # local name c is assigned a new object.
d[0] = 5 # local name d's object is mutated
print(' id(a) =',id(a),'value =',a)
print(' id(b) =',id(b),'value =',b) # b and d objects are same, so b changed
print(' id(c) =',id(c),'value =',c) # id changed, not same as a
print(' id(d) =',id(d),'value =',d) # id did not change, still same as b
d = [6] # local name d is assigned a new object.
print(' id(d) =',id(d),'value =',d) # id changed, not same as b
a = 3 # immutable
b = [3] # mutable
print('Before f()')
print(' id(a) =',id(a),'value =',a)
print(' id(b) =',id(b),'value =',b)
f(a,b)
print('After f()')
print(' id(a) =',id(a),'value =',a)
print(' id(b) =',id(b),'value =',b)
带注释的输出:
Before f()
id(a) = 507107264 value = 3
id(b) = 67001608 value = [3]
Inside f()
id(a) = 507107264 value = 3
id(b) = 67001608 value = [3]
id(c) = 507107264 value = 3 # id(c) == id(a)
id(d) = 67001608 value = [3] # id(d) == id(b)
id(a) = 507107264 value = 3
id(b) = 67001608 value = [5] # id(d)==id(b), so b changed when d did
id(c) = 507107296 value = 4 # c was reassigned, id(c) != id(a)
id(d) = 67001608 value = [5] # id(d) == id(b)...object mutated
id(d) = 65761864 value = [6] # d was reassigned, id(d) != id(b)
After f()
id(a) = 507107264 value = 3 # immutable a unaffected
id(b) = 67001608 value = [5] # sees mutation of list contents from d[0]=5
答案 1 :(得分:1)
list
是一个可变数据结构。这意味着您可以在保持id()
相同的同时更改其值。如果你传递一个命名这样一个对象的变量,因为它具有相同的id
,它与你在代码的各个部分中引用的对象相同。因此,如果你在任何地方改变它,那就好了。
所以解决方案是,不要传递它们。而保持它和在数据转换中使用它(而不是变异),即创建另一个或更好的使用生成器,并仅评估最终所需列表。