Python范围/静态误解

Ray*_*erg 6 python iteration scope class static-members

我真的坚持为什么下面的代码块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,]
Run Code Online (Sandbox Code Playgroud)

此代码的目标是迭代数组并将每个数据包装在父对象中.这是我的实际代码的减少,它将所有苹果添加到一袋苹果等等.我的猜测是,出于某种原因,它要么使用相同的对象,要么就像水果容器使用静态数组一样.我不知道如何解决这个问题.

Ned*_*der 8

您永远不应该使用可变值(如[])作为方法的默认参数.该值计算一次,然后用于每次调用.当您使用空列表作为默认值时,每次在没有参数的情况下调用方法时都会使用相同的列表,即使该值已被先前的函数调用修改.

改为:

def __init__(self,arr=None):
    self.array = arr or []
Run Code Online (Sandbox Code Playgroud)

  • 我真的不喜欢看到你通过查看值是否为false来测试`None`.最好使用`is None`测试.调用者可以合法地为初始化程序传递一个空列表,并且您的代码将丢弃该空列表并创建一个新的空列表...只有当某人试图使该类的多个实例共享相同时才会出现这种情况我想,最初是空的清单,但这是有可能的.无论如何,使用`is`来测试'None`是一个好习惯. (4认同)

ste*_*eha 2

您的代码有一个默认参数来初始化该类。默认参数的值在编译时计算一次,因此每个实例都使用相同的列表进行初始化。像这样改变它:

def __init__(self, arr=None):
    if arr is None:
        self.array = []
    else:
        self.array = arr
Run Code Online (Sandbox Code Playgroud)

我在这里更全面地讨论了这个问题:如何在Python中定义一个类