Reputation: 3352
GIVEN:
class A:
x = 4711
B = COPY(A)
setattr(B, "x", "0815")
print("A: %s; B: %s;" % (A.x, B.x))
GOAL:
An operation COPY
such that the code fragment above results in
A: 4711; B: 0815;
IN PLAIN WORDS:
By what means can a class object be deep-copied, so that it is totally isolated from its original. Using copy.deepcopy()
delivers
A: 0185; B: 0185;
so that is not the solution.
Upvotes: 1
Views: 2618
Reputation: 11232
from copy import deepcopy
class A:
x = 123
def __init__(self):
self.f()
def f(self):
print("original function", self.x)
def g(self):
print("replacement function", self.x)
B = deepcopy(A)
B.x = 456
B.f = g
a = A()
b = B()
This example prints:
replacement function 456
replacement function 456
Apparently, both A
as well as B
share the same values for their attributes x
and f
. Therefore, as you have already noted, copy.deepcopy
doesn't work to "copy" a class object. It seems that Python class objects are singletons, because A is deepcopy(A)
is True
.
So, alternatively, you could just use inheritance instead of copying:
class A:
x = 123
def __init__(self):
self.f()
def f(self):
print("original function", self.x)
def g(self):
print("replacement function", self.x)
class B(A):
pass
B.x = 456
B.f = g
a = A()
b = B()
Which prints:
original function 123
replacement function 456
Like this, we are able to change B.x
and B.f
without affecting A.x
and A.f
.
However, isinstance(b, A)
will be True
, which might be undesired. Also, changes to class attributes of A
will propagate to its child B
. Therefore, you just change your original A
into a dummy A_
, first, and then derive both A
and B
from that:
class A:
x = 123
def __init__(self):
self.f()
def f(self):
print("original function", self.x)
def g(self):
print("replacement function", self.x)
A_ = A
class A(A_):
pass
class B(A_):
pass
B.x = 456
B.f = g
a = A()
b = B()
Now, isinstance(b, A)
will be False
and changes to class attributes of A
will not propagate to B
.
Upvotes: 1