Reputation: 143
When calling on a new instance of an object for a class I've created, my one instance of the class is just being overwritten. Why could this be? Example is below.
My class is defined as follows:
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
I am making an initial instance as such:
root = my_class(some_attribute, data)
Then, I create another instance as such:
child = my_class(different_attribute, root.examples[somewhere_1:somewhere_2])
In the end, my initial 'root' is now somehow identical to 'child', where 'root' should have gone unchanged. Why is this!?
Upvotes: 2
Views: 2744
Reputation: 90882
When you define variables in the class definition, they are class attributes.
>>> my_class.examples is my_class().examples
True
(is
checks that they are exactly the same object, not just equal. For example, True == 1
, but True is not 1
.)
As list
s and dict
s are mutable, this means that changes in my_class.examples
or root.examples
or child.examples
will be reflected in all the others.
The way you should do such a thing is by setting it inside the constructor:
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
You probably also wish to replace self.examples = e
with self.examples = e[:]
which will make a shallow copy of the list. Otherwise:
>>> 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
Side-note: the recommended Python style would have your class as MyClass. I recommend that you read PEP 8.
Upvotes: 2
Reputation: 156278
I don't think you are doing with the initializations of attribute
, examples
, children
and d
what you think you are doing. Those are now attributes of the class, not of each instance. If you want each instance of the class to have its own attributes for attribute
, examples
, children
and d
, you should instead write:
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
Upvotes: 7