Python类 - 实例被覆盖?

2 投票
2 回答
2578 浏览
提问于 2025-04-16 07:04

当我调用我创建的类的新实例时,我的一个实例总是被覆盖。为什么会这样呢?下面是一个例子。

我的类定义如下:

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])

最后,我的初始“根”现在竟然和“子”是一样的,而“根”本来应该保持不变。为什么会这样呢!?

2 个回答

2

当你在类的定义中定义变量时,这些变量就是类属性。

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

(is 用来检查两个对象是否完全相同,而不仅仅是值相等。比如说,True == 1 是对的,但 True is not 1 是对的。)

因为 list(列表)和 dict(字典)是可变的,这意味着如果你在 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 的内容。

7

我觉得你对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

撰写回答