How to copy a ClassObject?

K

Karlo Lozovina

Hi all,

how would one make a copy of a class object? Let's say I have:
class First:
name = 'First'

And then I write:
tmp = First

then 'tmp' becomes just a reference to First, so if I write
tmp.name = "Tmp", there goes my First.name. So, how to make 'tmp' a copy
of First, I tried using copy.copy and copy.deepcopy, but that doesn't
work.

P.S.
Yes, I can do a:
class tmp(First):
pass

but I'd rather make a copy than a subclass.

Thanks.
 
M

Marc 'BlackJack' Rintsch

how would one make a copy of a class object? Let's say I have:
class First:
name = 'First'

And then I write:
tmp = First

then 'tmp' becomes just a reference to First, so if I write
tmp.name = "Tmp", there goes my First.name. So, how to make 'tmp' a copy
of First, I tried using copy.copy and copy.deepcopy, but that doesn't
work.

P.S.
Yes, I can do a:
class tmp(First):
pass

but I'd rather make a copy than a subclass.

Why? Python isn't a prototype based programming language.

Ciao,
Marc 'BlackJack' Rintsch
 
K

Karlo Lozovina

how would one make a copy of a class object? Let's say I have:
class First:
name = 'First'

And then I write:
tmp = First

Silly me, posted a question without Googling first ;>. This seems to be
the answer to my question:

import new
class First:
name = 'First'
tmp = new.classobj('tmp', (First,), {})

After this, tmp is a copy of First, and modifying tmp.name will not affect
First.name.

P.S.
If my code is somehow mistaken and might not function properly in all
cases, please correct me.

Bye,
klm.
 
P

Peter Otten

Karlo said:
Yes, I can do a:
  class tmp(First):
      pass

but I'd rather make a copy than a subclass.
tmp = new.classobj('tmp', (First,), {})

That line creates a subclass just as the simpler approach you gave above.

Peter
 
D

Duncan Booth

Karlo Lozovina said:
After this, tmp is a copy of First, and modifying tmp.name will not
affect First.name.

As Peter said, it's not a copy, its a subclass.

Modifying tmp.name would affect First.name (although in your example it is
immutable so you cannot modify it).
Also, rebinding First.name will change the value you see in tmp.name
whereas rebinding tmp.name will hide the copy inherited from First.name (so
a later del would restore it).
If my code is somehow mistaken and might not function properly in all
cases, please correct me.

Consider yourself corrected.

You could do what you are attempting with:

tmp = new.classobj('tmp', First.__bases__, dict(First.__dict__))

which creates a new class named 'tmp' with the same base classes and a copy
of First's __dict__ except that the __name__ attribute for the new class
will be set to 'tmp'. The attribute values are still shared between the
classes (which is significant only if they are mutable), but otherwise they
won't be sharing state.

I have no idea why you would want to do this, nor even why you would want a
'name' attribute when Python already gives you '__name__'.
 
S

Stargaming

Karlo said:
Silly me, posted a question without Googling first ;>. This seems to be
the answer to my question:

import new
class First:
name = 'First'
tmp = new.classobj('tmp', (First,), {})

After this, tmp is a copy of First, and modifying tmp.name will not affect
First.name.

P.S.
If my code is somehow mistaken and might not function properly in all
cases, please correct me.

Bye,
klm.
Leave out the `new` module and use `type()` (exactly the same call as to
`new.classobj`) to achieve the same effect.
 
P

Peter Otten

Stargaming said:
Leave out the `new` module and use `type()` (exactly the same call as to
`new.classobj`) to achieve the same effect.

No. new.classobj() creates a classic class whereas type() creates a
new-style class. Also,
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: a new-style class can't have only classic bases

Peter
 
K

Karlo Lozovina

Consider yourself corrected.

You could do what you are attempting with:

tmp = new.classobj('tmp', First.__bases__, dict(First.__dict__))

which creates a new class named 'tmp' with the same base classes and
a copy of First's __dict__ except that the __name__ attribute for the
new class will be set to 'tmp'. The attribute values are still shared
between the classes (which is significant only if they are mutable),
but otherwise they won't be sharing state.
I have no idea why you would want to do this, nor even why you would
want a 'name' attribute when Python already gives you '__name__'.

First of all, thanks for a clarification. 'name' attribute was just a
(dumb) example, it was the first thing to come to mind.

The idea behind all of this was to create classes dynamicaly, without
knowing in advance their names, or base class(es). So I figured I'd just
copy the base class and modify the attributes.
Instead, this way of subclassing seems to work just right for my purposes.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,679
Members
48,796
Latest member
Greg L.

Latest Threads

Top