how to deepcopy a slice object?

Alexandre Guimond alexandre.guimond at siemens.com
Wed Aug 16 03:42:38 EDT 2006


thx for all the help simon. good ideas i can work with.

thx again.

alex.

Simon Forman wrote:
> 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