我已经学习了一段时间的python,但它让我感到惊讶 我有以下代码:
def update_list(input_list):
input_list.append(len(input_list))
input_list[0] = 11
return input_list
def update_string(input_string):
input_string = 'NEW'
return input_string
my_list = [0,1,2]
print my_list
print update_list(my_list)
print my_list
my_string = 'OLD'
print my_string
print update_string(my_string)
print my_string
此代码提供以下输出:
[0, 1, 2]
[11, 1, 2, 3]
[11, 1, 2, 3]
OLD
NEW
OLD
为什么变量my_list
未经归因而被修改,my_string
值在update_string()
函数后保持不变?我不明白这个机制,你能解释一下吗?
答案 0 :(得分:3)
功能的行为没有什么不同。不同的是,在其中一个中你反弹名称:
input_string = 'NEW'
这将名称input_string
设置为新对象。在另一个函数中,您不对名称进行赋值。您只需在对象上调用方法,并在对象上分配索引。这恰好改变了对象内容:
input_list.append(len(input_list))
input_list[0] = 11
请注意,分配索引与分配名称不同。您可以先将列表对象分配给另一个名称,然后单独执行索引分配,什么都不会改变:
_temp = input_list
_temp[0] = 11
因为分配给索引会改变列表中包含的一个元素,而不是用于引用列表的名称。
如果您直接分配到input_list
,您会看到相同的行为:
input_list = []
input_list.append(len(input_list))
input_list[0] = 11
您也可以在功能之外执行此操作:
>>> a_str = 'OLD'
>>> b_str = a_str
>>> b_str = 'NEW'
>>> a_list = ['foo', 'bar', 'baz']
>>> b_list = a_list
>>> b_list.append('NEW')
>>> b_list[0] = 11
>>> a_str
'OLD'
>>> b_str
'NEW'
>>> a_list
[11, 'bar', 'baz', 'NEW']
>>> b_list
[11, 'bar', 'baz', 'NEW']
b_str
和b_list
的初始分配正是您调用函数时所发生的事情;函数的参数被赋予传递给函数的值。分配不会创建副本,它们会创建对该对象的其他引用。
如果您想传入列表对象的副本,请通过创建副本来执行此操作:
new_list = old_list[:] # slicing from start to end creates a shallow copy