1

我有一个带有一些属性字段的类,它是一个 numpy 数组。该类具有生成同一类的新实例的能力。现在我的问题是这样创建的所有实例似乎都指向同一个字段属性。因此,当给定代码的预期输出为:

[0, 0]

[1, 0]

[0, 2]

它实际上给出了:

[1, 2]

[1, 2]

[1, 2]

并且当我之后更改 a.field 中的条目时,该条目在所有实例的字段属性中都发生了更改

有人知道如何解决这个问题或者我在这里理解错了吗?

import numpy as np

class A:
    def __init__(self, field=np.zeros(2)):
        self.field=field

    def setField(self, c, index):
        if index<len(self.field):
            self.field[index]=c


    def multiply(self):

        new_A=np.empty(2, dtype=object)

        for n in range(0, 2, 1):
            new_A[n]=A()
            new_A[n].setField(n+1, n)

        return new_A



a=A()

subs=a.multiply()

print a.field
print subs[0].field
print subs[1].field
4

2 回答 2

1

这是每个人在学习 Python 时都会遇到的常见“陷阱”。它与 numpy 无关。例如,一个普通的列表会给你同样的行为。

>>> def f(x=[]):
...     x.append(1)
...     return x
... 
>>> f()
[1]
>>> f()
[1, 1]
>>> f()
[1, 1, 1]

粗略地说,该代码被解释为如下所示:

f_default_arg_x = []
def f(x=f_default_arg_x):
    x.append(1)
    return x

一旦您意识到这个问题的存在,您可以找到很多页面来解释问题并告诉您如何处理它。(例如:http ://effbot.org/zone/default-values.htm )

通常的解决方案是仅用None作“请提供默认值”的占位符。

def f(x=None):
    if x is None:
        x = []
    x.append(1)
    return x
于 2014-09-16T23:00:51.387 回答
0

您不应该将数组作为默认参数,而应该像这样定义它:

class A:
    def __init__(self, field=None):
        if field is None:
            field = np.zeros(2)

        self.field=field

    def setField(self, c, index):
        if index<len(self.field):
            self.field[index]=c


    def multiply(self):

        new_A=np.empty(2, dtype=object)

        for n in range(0, 2, 1):
            new_A[n]=A()
            new_A[n].setField(n+1, n)

        return new_A

查看Python 中的“Least Astonishment”:可变默认参数,详细解释为什么不应该使用列表或数组作为默认参数。

于 2014-09-15T14:17:22.097 回答