how to deepcopy a slice object?
Simon Forman
rogue_pedro at yahoo.com
Tue Aug 15 17:37:42 EDT 2006
Alexandre Guimond wrote:
> Here is my reason:
>
> I have an object that contrains a 2D regular grid (matrix). In this
> regular grid, I place points at regular intervals. In essence, i have
> something like (my code is obviously more complex, this is just to show
> what I want to do)
>
> obj.grid = numpy.zeros( ( 100, 100 ) )
> obj.grid[ obj.y1: obj.y2 : obj.ys, obj.x1 : obj.x2 : obj.xs ] =
> embedded_parameters
> result = somefunc( obj.grid )
>
> My goal was to reduce the number of elements in my obj object by
> replacing y1, y2, ys, and x1, x2, xs by 2 slice objects, and then do:
>
> obj.grid[ obj.slicey, obj.slicex ] = embedded_parameters
>
> But when I do this and then try to deepcopy my object, it doesn't work,
> as in the example below.
>
> Its not a big thing. I just liked the idea of having less elements in
> my obj class and actually modeling my slice concept by a slice object,
> specially since i'm going to 3D and 4D grid, and its somewhat annoying
> to carry so many indices in my class definition.
>
> Simon Forman wrote:
> > Alexandre Guimond wrote:
> > > Hi all,
> > >
> > > i'm trying to deepcopy a slice object but i get the following error.
> > > Does anyone know a workaround?
> > >
> > > ActivePython 2.4.3 Build 12 (ActiveState Software Inc.) based on
> > > Python 2.4.3 (#69, Apr 11 2006, 15:32:42) [MSC v.1310 32 bit (Intel)]
> > > on win32
> > > Type "help", "copyright", "credits" or "license" for more information.
> > > >>> import copy
> > > >>> copy.deepcopy( slice( 1, 10, 2 ) )
> > > Traceback (most recent call last):
> > > File "<stdin>", line 1, in ?
> > > File "C:\Program Files\Python\lib\copy.py", line 204, in deepcopy
> > > y = _reconstruct(x, rv, 1, memo)
> > > File "C:\Program Files\Python\lib\copy.py", line 336, in _reconstruct
> > > y = callable(*args)
> > > File "C:\Program Files\Python\lib\copy_reg.py", line 92, in
> > > __newobj__
> > > return cls.__new__(cls, *args)
> > > TypeError: slice expected at least 1 arguments, got 0
> > >
> > > thx for any help.
> >
> > Why would you want to [deep]copy a slice object?
> >
> > Anyway, I don't know much about them, other than that they are
> > slightly unusual objects that play a very restricted role in python,
> > rather like the Ellipsis.
> >
> > Workarounds are possible, I think, but really you almost certainly
> > don't need to do this.
> >
> > Peace,
> > ~Simon
Ah, so you *do* want to deepcopy slice objects.. Neat. :-)
I can't do that, but I can show you a couple of ways to deepcopy
objects that have slices as attributes.
First, if the __init__() method and its args are sufficient to recreate
your objects then you could do something like this:
class DeepCopyable0:
def __init__(self, x, y, z, a, b, c):
self.slicex = slice(x, y, z)
self.slicey = slice(a, b, c)
def __deepcopy__(self, memo):
# Create local vars for brevity.
sx, sy = self.slicex, self.slicey
# Create a new DeepCopyable0 instance.
return DeepCopyable0(
sx.start, sx.stop, sx.step,
sy.start, sy.stop, sy.step
)
|>> d0 = DeepCopyable0(1, 2, 3, 4, 5, 6)
|>> d0.slicex, d0.slicey
(slice(1, 2, 3), slice(4, 5, 6))
|>> d1 = deepcopy(d0)
|>> d1.slicex, d1.slicey
(slice(1, 2, 3), slice(4, 5, 6))
Otherwise, another way to do it would be to provide the pickling
protocol:
class DeepCopyable1:
def __init__(self, x, y, z, a, b, c):
# Pretend this was something more complicated.
self.slicex = slice(x, y, z)
self.slicey = slice(a, b, c)
def __getstate__(self):
state = self.__dict__.copy()
# Create local vars for brevity.
sx, sy = self.slicex, self.slicey
# Save the indices rather than the slices.
state['slicex'] = sx.start, sx.stop, sx.step
state['slicey'] = sy.start, sy.stop, sy.step
return state
def __setstate__(self, state):
# Recreate the slice objects.
state['slicex'] = slice(*state['slicex'])
state['slicey'] = slice(*state['slicey'])
self.__dict__.update(state)
|>> d0 = DeepCopyable1(1, 2, 3, 4, 5, 6)
|>> d0.slicex, d0.slicey
(slice(1, 2, 3), slice(4, 5, 6))
|>> d1 = deepcopy(d0)
|>> d1.slicex, d1.slicey
(slice(1, 2, 3), slice(4, 5, 6))
Circular references seem work fine here too. Observe:
|>> d0 = DeepCopyable1(1, 2, 3, 4, 5, 6)
|>> d0.rec = d0
|>> d0
<delme.DeepCopyable instance at 0xb7d5cb2c>
|>> d0.rec.rec #etc...
<delme.DeepCopyable instance at 0xb7d5cb2c>
|>> d1 = deepcopy(d0)
|>> d1
<delme.DeepCopyable instance at 0xb7d7878c>
|>> d1.rec
<delme.DeepCopyable instance at 0xb7d7878c>
Since you're going to be using more dimensions, you could make python
do the work for you rather than cutting and pasting:
class DeepCopyable2:
# __init__() omitted...
def __getstate__(self):
state = self.__dict__.copy()
# Keep track of the slice attributes
slices = state['slices'] = []
# Convert slices to indices.
for attr, s in state.items():
if isinstance(s, slice):
state[attr] = s.start, s.stop, s.step
slices.append(attr)
return state
def __setstate__(self, state):
slices = state.pop('slices')
# Recreate the slice objects.
for attr in slices:
state[attr] = slice(*state[attr])
self.__dict__.update(state)
(I copied over the __init__() method from DeepCopyable for this
example.)
|>> from delme import *
|>> d0 = DeepCopyable2(1, 2, 3, 4, 5, 6)
|>> d1 = deepcopy(d0)
|>> d1.slicex, d1.slicey
(slice(1, 2, 3), slice(4, 5, 6))
HTH. :)
I haven't used numpy (yet) and I've never explicitly used slice
objects, so the idea of storing and copying them struck me funny. I
find it very interesting and amusing that someone somewhere has a use
for them like this.
Peace,
~Simon
More information about the Python-list
mailing list