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])
最后,我的初始“根”现在竟然和“子”是一样的,而“根”本来应该保持不变。为什么会这样呢!?
2 个回答
2
当你在类的定义中定义变量时,这些变量就是类属性。
>>> my_class.examples is my_class().examples
True
(is
用来检查两个对象是否完全相同,而不仅仅是值相等。比如说,True == 1
是对的,但 True is not 1
是对的。)
因为 list
(列表)和 dict
(字典)是可变的,这意味着如果你在 my_class.examples
、root.examples
或 child.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
我觉得你对attribute
、examples
、children
和d
的初始化处理得并不像你想的那样。现在这些是类的属性,而不是每个实例的属性。如果你想让每个类的实例都有自己的attribute
、examples
、children
和d
属性,你应该这样写:
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