Alexandre said:
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 said:
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