4

I have a python object which is essentially a collection of other object instances. You can append other objects to it (which it just stores in a list). It is created when reading a file, eg:

def file_reader(file):
    obj = MyCollection()

    for line in file:
        other_obj = line_reader(line)
        obj.append(other_obj)
    return obj

If I then try to overwrite the object later (by reading a different file), the original data is not deleted, the object is just extended. Strangely, this seems to happen if I use different references:

obj1 = file_reader(file)
obj2 = file_reader(file1)

I suspect I have some kind of problem with circular referencing, but I can't quite grasp the logic. Anyone have an idea?

Edit: The essential part of MyCollection looks like:

class MyCollection(object):

    def __init__(self, objs = []):
        self.objs = objs

   def append(self, obj):
        self.objs.append(obj)
3
  • 2
    Could you show the code for MyCollection()? I'm betting the list is a class attribute, not an instance attribute. Commented Jan 27, 2014 at 13:56
  • Could you provide us, please, with the code of MyCollection object? It could be helpful. Commented Jan 27, 2014 at 13:58
  • edited the question to add the collection class Commented Jan 27, 2014 at 14:02

1 Answer 1

8

I'll take a not-so-wild guess that you currently have something like this:

class MyCollection():
    listOfThings = []
    def __init__(self):

In this case, listOfThings is a class attribute, it is shared amongst all instances of the MyCollection class. Instead, you want an instance attribute, separate for each instance:

class MyCollection():
    def __init__(self):
        self.listOfThings = []

Edit: so close!

The issue you have is in:

def __init__(self, objs = []):

Here, objs is known as a "mutable default parameter". The list in the default parameter values is shared for all instances of that class that don't pass anything to __init__ (defining a = MyCollection([]), for instance, would create a new instance with a separate objs list).

You should use:

def __init__(self, objs=None):
    if objs is None:
        objs = []

Canonical question covering this: "Least Astonishment" and the Mutable Default Argument

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks a lot! I had to look up 'mutable default parameter', and presto, my exact example is in the guide: docs.python-guide.org/en/latest/writing/gotchas
BTW, list is not used as the actual class is a fair bit bigger with other methods. You hit the problem though :)
Yes, this is a classic example of something that is incredibly easy to find information on, but only if you already know what it's called!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.