socks_swerve
socks_swerve

Reputation: 143

Python classes - instances being overwritten?

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

Answers (2)

Chris Morgan
Chris Morgan

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 lists and dicts 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

SingleNegationElimination
SingleNegationElimination

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

Related Questions