Why do list operations in python operate outside of the function scope?
本问题已经有最佳答案,请猛点这里访问。
在下面的python代码中,变量
1 2 3 4 5 6 7 8 | def addone(num): num = num + 1 print"function: added 1, now %d" % num number = 5 print"Before:", number addone(number) print"After:", number |
输出:
1 2 3 | Before: 5 function: added 1, now 6 After: 5 |
但是,该行为似乎与诸如pop、append等列表操作不同。这让我有些困惑。所有列表操作是否在全球范围内运行?如果是这样,背后有什么特别的原因吗?
1 2 3 4 5 6 7 8 | def pop_first(stuff): popped = stuff.pop(0) print"function: '%s' was popped!" % popped words = ["A","list","of","words"] print"Before:", words pop_first(words) print"After:", words |
输出:
1 2 3 | Before: ['A', 'list', 'of', 'words'] function: 'A' was popped! After: ['list', 'of', 'words'] |
简短的答案是因为列表是可变的,整数是不可变的。
不能在适当的位置改变整数,所以我们称之为"不可变"。考虑到这一点,像在整数上加法这样的事情不会修改原始对象,而是返回一个新的值-因此原始变量将保持不变。因此,如果我们存储一个对整数的引用,那么只要我们没有更改它们中的任何一个,它们就只是同一个对象:
1 2 3 4 5 6 7 8 9 10 11 12 | >>> foo = 1 >>> bar = foo >>> foo is bar True >>> foo += 2 3 >>> foo 3 >>> bar 1 >>> foo is bar False |
另一方面,列表是"可变的"(可以修改同一个对象引用),像
1 2 3 4 5 6 7 8 9 10 11 12 | >>> baz = [1, 2, 3, 4, 5] >>> qux = baz >>> qux is baz True >>> baz.pop() 5 >>> qux [1, 2, 3, 4] >>> baz [1, 2, 3, 4] >>> qux is baz True |
将对象传递给函数的方式与分配对象的方式相同。所以,你看到的效果和这个一样:
1 2 3 4 5 6 | >>> words = ["A","list","of","words"] >>> stuff = words >>> stuff.pop() 'words' >>> words ['A', 'list', 'of'] |
这是因为
1 2 3 4 5 6 7 8 9 | >>> stuff is words True >>> a = 5 >>> b = a >>> a is b True >>> b += 1 >>> a is b False |
当执行
1 2 3 4 5 6 7 8 9 10 11 12 13 | def addone(num): num = num + [1] print"function: added 1, now", num number = [5] print"Before:", number addone(number) print"After:", number # Before: [5] # function: added 1, now [5, 1] # After: [5] |