Python:为什么class方法中的本地列表变量保留其值?

时间:2016-12-31 19:03:57

标签: python-2.7 list class methods

我四处搜寻,发现this article让我了解了为什么会发生这种情况 - 我似乎只是遇到了一个更为复杂和微妙的案例。但令我感到困惑的是那些微妙之处,并寻求更清晰的解释。 (我怀疑这很重要,但以防万一:我在Windows 7上使用Python 2.7.x。)

起点是这段代码,我从一个更大,更复杂的应用程序中提炼出来,我第一次遇到问题。

class MyClass():
    def printStuff(self,myList=[1,2,3],myInt=4):
        print '--------------------------------'
        print 'myList at start: '+str(myList)
        print 'myInt  at start: '+str(myInt)
        doNotCare = myList.pop()
        myInt = myInt - 1
        print 'myList at end:   '+str(myList)
        print 'myInt  at end:   '+str(myInt)

testMC = MyClass()
testMC.printStuff()
testMC.printStuff()
testMC.printStuff()

...生成以下输出:

--------------------------------
myList at start: [1, 2, 3]
myInt  at start: 4
myList at end:   [1, 2]
myInt  at end:   3
--------------------------------
myList at start: [1, 2]
myInt  at start: 4
myList at end:   [1]
myInt  at end:   3
--------------------------------
myList at start: [1]
myInt  at start: 4
myList at end:   []
myInt  at end:   3

现在,基于关于如何在函数中处理默认参数的各种报道,似乎myInt应该表现出与myList相同的行为,即它应该递减到3,2,但显然它没有。

如果我修改doNotCare = myList.pop()行,而不是使用切片来更新列表,那么这个难题会变得更复杂:

class MyClass():
    def printStuff(self,myList=[1,2,3],myInt=4):
        print '--------------------------------'
        print 'myList at start: '+str(myList)
        print 'myInt  at start: '+str(myInt)
        myList = myList[:-1]
        myInt = myInt - 1
        print 'myList at end:   '+str(myList)
        print 'myInt  at end:   '+str(myInt)

testMC = MyClass()
testMC.printStuff()
testMC.printStuff()
testMC.printStuff()

...以某种方式击败了意外的保留值,产生了输出:

--------------------------------
myList at start: [1, 2, 3]
myInt  at start: 4
myList at end:   [1, 2]
myInt  at end:   3
--------------------------------
myList at start: [1, 2, 3]
myInt  at start: 4
myList at end:   [1, 2]
myInt  at end:   3
--------------------------------
myList at start: [1, 2, 3]
myInt  at start: 4
myList at end:   [1, 2]
myInt  at end:   3

所以我想第一个问题是,这实际上只是参考文献中描述的默认参数行为的一个更复杂和微妙的情况吗?如果是,那么当我使用切片而不是myInt操纵行为时,为什么行为不适用于myList - 甚至适用于pop

1 个答案:

答案 0 :(得分:1)

与列表不同,数字是不可变的,因此无法更改。可以重新分配对它们的引用,但1将始终为1。

拼接不会产生此行为,因为它会创建原始副本,而pop会修改原始列表。