为什么python中的列表操作在函数范围之外运行?

时间:2014-04-12 11:24:40

标签: python list scope

在下面的python代码中,变量number被传递给函数addone,并且操作本地副本。数字的值保持不变。

def addone(num):
    num = num + 1
    print "function: added 1, now %d" % num

number = 5
print "Before:", number
addone(number)
print "After:", number

输出:

Before: 5
function: added 1, now 6
After: 5

然而,行为似乎与pop,append等列表操作不同。这有点让我感到困惑。所有列表操作是否全局运行?如果是这样,背后有什么特别的原因吗?

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

输出:

Before: ['A', 'list', 'of', 'words']
function: 'A' was popped!
After: ['list', 'of', 'words']

3 个答案:

答案 0 :(得分:4)

简短回答是因为列表可变,整数不可变


你不能改变一个整数,所以我们称之为'不可变'。考虑到这一点,像整数上的加法之类的东西不会修改原始对象,而是返回一个新值 - 因此原始变量将保持不变。因此,如果我们存储对整数的引用,只要我们没有更改其中任何一个,它们将只是同一个对象:

>>> foo = 1
>>> bar = foo
>>> foo is bar
True
>>> foo += 2
3
>>> foo
3
>>> bar
1
>>> foo is bar
False

另一方面,列表是“可变的”(可以修改相同的对象引用),像pop()这样的操作会原位变换list,更改原始列表。这也意味着如果您编辑对list等可变对象的引用,原始内容也会更改:

>>> 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 :(得分:1)

将对象传递给函数的工作方式与分配它们的方式相同。所以,你所看到的效果与此相同:

>>> words = ["A", "list", "of", "words"]
>>> stuff = words
>>> stuff.pop()
'words'
>>> words
['A', 'list', 'of']

这是因为stuffwords 相同的列表,而pop更改了该列表。 int是不可变的,这意味着它们不支持任何就地突变:每次更改其值时,它都会为您提供具有新值的不同的 int对象。您可以使用is运算符测试两个对象是相同还是不同的对象:

>>> stuff is words
True
>>> a = 5
>>> b = a
>>> a is b
True
>>> b += 1
>>> a is b
False

答案 2 :(得分:0)

执行stuff.pop()时,您需要修改对象stuff。执行num = num + 1后,您不会修改num,只需创建一个新对象并将其分配给变量num即可。如果num是一个列表,结果将完全相同:

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]