Any way to refactor this?
John Krukoff
jkrukoff at ltgc.com
Fri Apr 13 17:56:27 EDT 2007
Bruno Desthuilliers wrote:
> John Salerno a écrit :
> > Setting aside, for the moment, the utility of this method or even if
> > there's a better way, I'm wondering if this is an efficient way to do
> > it. I admit, there was some copying and pasting, which is what prompts
> > me to ask the question. Here's the method. (I hope it looks ok, because
> > it looks really weird for me right now)
> >
> > def _create_3D_xhatches():
> > for x in xrange(-axis_length, axis_length + 1):
> > if x == 0: continue
> > visual.cylinder(pos=(x,-hatch_length,0),
> > axis=(0,hatch_length*2,0), radius=hatch_radius)
> > visual.cylinder(pos=(x,0,-hatch_length),
> > axis=(0,0,hatch_length*2), radius=hatch_radius)
> > visual.cylinder(pos=(-hatch_length,x,0),
> > axis=(hatch_length*2,0,0), radius=hatch_radius)
> > visual.cylinder(pos=(0,x,-hatch_length),
> > axis=(0,0,hatch_length*2), radius=hatch_radius)
> > visual.cylinder(pos=(-hatch_length,0,x),
> > axis=(hatch_length*2,0,0), radius=hatch_radius)
> > visual.cylinder(pos=(0,-hatch_length,x),
> > axis=(0,hatch_length*2,0), radius=hatch_radius)
> >
> > Since each call to cylinder requires a slightly different format, I
> > figured I had to do it this way.
>
> From a purely efficiency POV, there are some obviously possible
> improvements. The first one is to alias visual.cylinder, so you save on
> lookup time. The other one is to avoid useless recomputation of
> -hatch_length and hatch_length*2.
>
> def _create_3D_xhatches():
> cy = visual.cylinder
> for x in xrange(-axis_length, axis_length + 1):
> if x == 0: continue
> b = -hatch_length
> c = hatch_length*2
> cy(pos=(x, b, 0), axis=(0, c, 0), radius=hatch_radius)
> cy(pos=(x, 0, b), axis=(0, 0, c), radius=hatch_radius)
> cy(pos=(b, x, 0), axis=(c, 0, 0), radius=hatch_radius)
> cy(pos=(0, x, b), axis=(0, 0, c), radius=hatch_radius)
> cy(pos=(b, 0, x), axis=(c, 0, 0), radius=hatch_radius)
> cy(pos=(0, b, x), axis=(0, c, 0), radius=hatch_radius)
>
> A second step would be to try and generate the permutations by code
> instead of writing them all by hand, but I suppose the order is
> significant...
> There's still an obvious pattern, which is that the position of 'c' in
> the axis tuple mirrors the position of 'b' in the pos tuple. There might
> be some way to use this to let the computer handle some part of the
> repetition...
>
> My 2 cents...
> --
> http://mail.python.org/mailman/listinfo/python-list
Because it was fun, and the previous refactoring made the pattern easy to
see, here's the way not to do this. (Requires python 2.5 for trinary
operator)
# From the ASPN cookbook
def permutations(L):
if len(L) <= 1:
yield L
else:
a = [L.pop(0)]
for p in permutations(L):
for i in range(len(p)+1):
yield p[:i] + a + p[i:]
def _create_3D_xhatches():
for x in xrange(-axis_length, axis_length + 1):
if x <> 0:
# Use None as placeholder for comparison.
for pos in permutations([x, None, 0]):
visual.cylinder(pos = [-hatch_length if coord is None else
coord for coord in pos], axis = [hatch_length * 2 if coord is None else 0
for coord in pos], radius = hatch_radius)
Undoubtedly slower, nearly impossible to read, but has minimum of code
duplication!
If I was answering this question for real, I'd suggest the same arguments as
tuple solution that was suggested earlier, i.e.:
def _create_3D_xhatches():
list_of_kwargs = [
{pos:[ x, -hatch_length, 0], axis:[0, 2 * hatch_length, 0 ]},
{pos:[ x, 0, -hatch_length], axis:[0, 0, 2 * hatch_length ]},
And so on for all permutations...
]
for x in xrange(-axis_length, axis_length + 1):
if x == 0:
continue
for kwargs in list_of_kwargs:
visual.cylinder( radius = hatch_radius, **kwargs )
As it pulls out the two obviously common components, the function call and
the radius parameter.
---------
John Krukoff
jkrukoff at ltgc.com
More information about the Python-list
mailing list