Python类 - 被覆盖的实例?

时间:2010-11-15 00:07:32

标签: python

当我为我创建的类调用一个对象的新实例时,我的一个类实例就被覆盖了。为什么会这样?示例如下。

我的课程定义如下:

class my_class:
    attribute = ""
    examples = [] 
    children = []
    d = {}
    def __init__(self, attribute, e):
        self.attribute = attribute
        self.examples = e

        for ex in self.examples:
            self.d[ex[-1]] = self.d.get(ex[-1], 0) + 1

我正在制作一个初始实例:

root = my_class(some_attribute, data)

然后,我创建了另一个实例:

child = my_class(different_attribute, root.examples[somewhere_1:somewhere_2])

最后,我的初始'root'现在与'child'在某种程度上相同,其中'root'应该保持不变。这是为什么!?

2 个答案:

答案 0 :(得分:6)

我认为您正在使用attributeexampleschildrend初始化您认为自己正在做的事情。这些现在是类的属性,而不是每个实例的属性。如果您希望类的每个实例都有attributeexampleschildrend的自己的属性,那么您应该写:

class my_class:
    def __init__(self, attribute, e):

        self.attribute = attribute
        self.examples = e
        self.children = []
        self.d = {}

        for ex in self.examples:
            self.d[ex[-1]] = self.d.get(ex[-1], 0) + 1

答案 1 :(得分:2)

在类定义中定义变量时,它们是类属性。

>>> my_class.examples is my_class().examples
True

is检查它们是完全相同的对象,而不仅仅是相等的。例如,True == 1,但是True is not 1。)

由于listdict s是可变的,这意味着my_class.examplesroot.exampleschild.examples中的更改将反映在所有其他内容中。

你应该这样做的方法是在构造函数中设置它:

class my_class:
    def __init__(self, attribute, e):
        self.attribute = attribute
        self.examples = e 
        self.children = []
        self.d = {}

        for ex in self.examples:
            self.d[ex[-1]] = self.d.get(ex[-1], 0) + 1

您可能还希望将self.examples = e替换为self.examples = e[:],这将生成列表的浅表副本。否则:

>>> data
[1, 2, 3, 4, 5]
>>> root = my_class(some_attribute, data)
>>> root.examples
[1, 2, 3, 4, 5]
>>> data += [6, 7]
>>> root.examples
[1, 2, 3, 4, 5, 6, 7]
>>> # ... because:
>>> root.examples is data
True

旁注:推荐的Python样式将您的类作为MyClass。我建议你阅读PEP 8。