Python范围/静态误解
我真的搞不懂为什么下面的代码块1会输出结果1,而不是结果2?
代码块1:
class FruitContainer:
def __init__(self,arr=[]):
self.array = arr
def addTo(self,something):
self.array.append(something)
def __str__(self):
ret = "["
for item in self.array:
ret = "%s%s," % (ret,item)
return "%s]" % ret
arrayOfFruit = ['apple', 'banana', 'pear']
arrayOfFruitContainers = []
while len(arrayOfFruit) > 0:
tempFruit = arrayOfFruit.pop(0)
tempB = FruitContainer()
tempB.addTo(tempFruit)
arrayOfFruitContainers.append(tempB)
for container in arrayOfFruitContainers:
print container
**Output 1 (actual):**
[apple,banana,pear,]
[apple,banana,pear,]
[apple,banana,pear,]
**Output 2 (desired):**
[apple,]
[banana,]
[pear,]
这段代码的目的是遍历一个数组,把每个元素放到一个父对象里。这是我实际代码的简化版,实际代码是把所有的苹果放到一个苹果袋里,依此类推。我猜可能是因为某种原因,它要么在使用同一个对象,要么就像水果容器使用了一个静态数组一样。我不知道该怎么解决这个问题。
4 个回答
1
正如Ned所说,你的问题在于你把一个列表当作默认参数使用了。这里有更多的细节可以查看这里。解决办法是把__init__
函数改成下面这样:
def __init__(self,arr=None):
if arr is not None:
self.array = arr
else:
self.array = []
8
你绝对不要把可变的值(比如空列表 [])作为方法的默认参数。这个值只会计算一次,然后在每次调用这个方法的时候都用同一个值。如果你把一个空列表当作默认值,那么每次调用这个方法而没有提供参数时,都会使用同一个列表,哪怕这个列表在之前的函数调用中已经被修改过了。
可以这样做:
def __init__(self,arr=None):
self.array = arr or []
2
你的代码在初始化类的时候使用了一个默认参数。这个默认参数的值只在编译时计算一次,所以每次创建的实例都会用同一个列表来初始化。你可以这样修改:
def __init__(self, arr=None):
if arr is None:
self.array = []
else:
self.array = arr
我在这里详细讨论过这个问题:如何在Python中定义一个类