Copying objects and multiple inheritance
Brian Allen Vanderburg II
BrianVanderburg2 at aim.com
Wed Jun 3 09:20:35 EDT 2009
Gabriel Genellina wrote:
> En Tue, 02 Jun 2009 19:02:47 -0300, Brian Allen Vanderburg II
> <BrianVanderburg2 at aim.com> escribió:
>
>> What is the best way to copy an object that has multiple inheritance
>> with the copy module. Particularly, some of the instances in the
>> hierarchy
>
> ("...some of the classes in...", I presume?)
>
>> use the __copy__ method to create a copy (because even for shallow
>> copies they need some information updated a little differently), so
>> how can I make sure all the information is copied as it is supposed
>> to be even for the base classes that have special requirements.
>
> If you don't control all the clases involved, there is little hope for
> a method like __copy__ to work at all... All classes must be written
> with cooperation in mind, using super() the "right" way. See "Python's
> Super Considered Harmful" [1] and "Things to Know About Python Super"
> [2][3][4]
>
> That said, and since multiple inheritance is the heart of the problem,
> maybe you can redesign your solution *without* using MI? Perhaps using
> delegation instead?
>
> [1] http://fuhm.net/super-harmful/
> [2] http://www.artima.com/weblogs/viewpost.jsp?thread=236275
> [3] http://www.artima.com/weblogs/viewpost.jsp?thread=236278
> [4] http://www.artima.com/weblogs/viewpost.jsp?thread=237121
>
I do control the classes involved. A problem I was having, but I think
I now got solved, is if using super, the copy would not have the same
class type. Also, a problem was if using super, but some class in the
hierarchy didn't implement __copy__, then it's data would not be copied
at all. This was also fixed by copying the entire __dict__ in the base
__copy__. This is an idea of what I got, it seems to be working fine:
import copy
class _empty(object):
pass
class Base(object):
def __init__(self):
pass
def __copy__(self):
// don't use copy = Base()
// Also don't call self.__class__() because it may have a custom
// __init__ which take additional parameters
copy = _empty()
copy.__class__ = self.__class__
// In case a class does not have __copy__ (such as B below), make
// sure all items are copied
copy.__dict__.update(self.__dict__)
return copy
class A(Base):
def __init__(self):
super(A, self).__init__()
self.x = 13
def __copy__(self):
copy = super(A, self).__copy__()
copy.x = self.x * 2
return copy
class B(Base):
def __init__(self):
super(B, self).__init__()
self.y = 14
#def __copy__(self):
# copy = super(B, self).__copy__()
# copy.y = self.y / 2
# return copy
class C(A, B):
def __init__(self):
super(C, self).__init__()
self.z = 64
def __copy__(self):
copy = super(C, self).__copy__()
copy.z = self.z * self.z
return copy
o1 = C()
o2 = copy.copy(o1)
print type(o1), o1.x, o1.y, o1.z
print type(o2), o2.x, o2.y, o2.z
More information about the Python-list
mailing list