python中函数的不同行为

时间:2016-01-11 18:15:54

标签: python python-2.7

我已经学习了一段时间的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()函数后保持不变?我不明白这个机制,你能解释一下吗?

1 个答案:

答案 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_strb_list的初始分配正是您调用函数时所发生的事情;函数的参数被赋予传递给函数的值。分配不会创建副本,它们会创建对该对象的其他引用。

如果您想传入列表对象的副本,请通过创建副本来执行此操作:

new_list = old_list[:]  # slicing from start to end creates a shallow copy