tastyminerals
tastyminerals

Reputation: 6548

Why copied objects have the same id as previously copied ones in Python?

I am trying to understand one observation. I have an application that loads various Canvas classes which a user can later work with. These classes are located in several files. For example.

canvas/
    bw.py
    colored.py
    oil.py

I import, instantiate and copy these objects like this:

canvas_files = os.listdir('images')
imported_canvs = []
    for canv in canvas_files:
        canv = __import__(canv.split('.')[0], fromlist=['Canvas'])
        try:
            new_canv = canv.Canvas()
            new_canv_copy = copy.copy(new_canv)
            imported_canvs.append(new_canv_copy)
        except AttributeError as ex:
             pass

Afterwards, a user works with each Canvas object from imported_canvs list. However, when I import and instantiate these objects twice (run the for loop again) I can see id(new_canv_copy) is the same as previously imported and instantiated ones. This would not be a problem unless that each Canvas has settings which should be unique for each instance and this is not currently happening. Whenever a user changes the settings in one Canvas they are automatically changed in the copied one.

Why is this happening and what am I doing wrong?

Upvotes: 1

Views: 60

Answers (3)

Nikita
Nikita

Reputation: 6341

Regarding your note on running the for loop several times ad getting the same id's... It might not be the problem with copy.copy, as it copies top-level object and id's for top-level mutable objects should differ, but id's for inner mutable objects will stay the same, unlike copy.deepcopy where all mutable objects id's should differ.

Probably it's the issue with the __import__ itself...

When you import a module in Python, it's imported only once. So when you issue the first import of the module 'some_module_a.py' it is imported, and then, when you issue a second import of the same module 'some_module_a.py' it's not imported again, but the reference to the already imported module is reused/returned.

So if you need to re-import the same module more than once, import it for the first time and then use importlib.reload to have it trully imported again.

Upvotes: 1

martin
martin

Reputation: 96959

Using just copy.copy() creates a shallow copy. You probably want to use deep copy when copying objects using copy.deepcopy().

You can read in detail what's the difference here: https://docs.python.org/2/library/copy.html

I don't know what canv.Canvas() does inside so it's hard to tell what's going on when you run the same code twice when I can't try it by myself.

Upvotes: 1

Sami Kuhmonen
Sami Kuhmonen

Reputation: 31183

copy.copy performs a shallow copy, meaning any objects will point to existing objects. If you want the objects inside it also to be cloned, you need to use copy.deepcopy.

Upvotes: 0

Related Questions