From: Alain Ketterlin on
Lawrence D'Oliveiro <ldo(a)geek-central.gen.new_zealand> writes:

>>> V = tuple \
>>> (
>>> x
>>> /
>>> l
>>> for x in V
>>> for l in
>>> (math.sqrt(reduce(lambda a, b : a + b, (y * y for y in V),
>>> 0)),)
>>> )
>>
>> You got the order wrong (it has to be for l ... for x ...)
>
> No, I deliberately put it in that order to ensure that the value for l can
> only ever be evaulated once.

Try this (essentially equivalent to your code):

def f():
print "hello"
return 1

V = tuple( 1 for x in [1,2,3] for l in (f(),) )

How many "hello"s do you see?

Comprehension are not loops spelled backwards. The values in:

whatever for i ... for j ...

are the values produced by the equivalent code:

for i ...
for j ...
whatever

-- Alain.
From: Terry Reedy on
On 7/30/2010 7:46 AM, Lawrence D'Oliveiro wrote:
> Say a vector V is a tuple of 3 numbers, not all zero. You want to normalize
> it (scale all components by the same factor) so its magnitude is 1.
>
> The usual way is something like this:
>
> L = math.sqrt(V[0] * V[0] + V[1] * V[1] + V[2] * V[2])
> V = (V[0] / L, V[1] / L, V[2] / L)
>
> What I don’t like is having that intermediate variable L leftover after the
> computation.

So, instead of fooling around with error-prone, hard-to-type
constructions, just delete the damn thing!

def L

Compare those foolproof 5 chars to what at first did not work right and
even what did. And, as other said, in most real applications, you will
normalize in more than one place. In fact, you may well want a vlen
function.

def vlen(seq): return math.sqrt(sum(x*x for x in seq))

--
Terry Jan Reedy


From: Matteo Landi on
On Mon, Aug 2, 2010 at 1:50 AM, Terry Reedy <tjreedy(a)udel.edu> wrote:
> On 7/30/2010 7:46 AM, Lawrence D'Oliveiro wrote:
>>
>> Say a vector V is a tuple of 3 numbers, not all zero. You want to
>> normalize
>> it (scale all components by the same factor) so its magnitude is 1.
>>
>> The usual way is something like this:
>>
>>     L = math.sqrt(V[0] * V[0] + V[1] * V[1] + V[2] * V[2])
>>     V = (V[0] / L, V[1] / L, V[2] / L)
>>
>> What I don’t like is having that intermediate variable L leftover after
>> the
>> computation.
>
> So, instead of fooling around with error-prone, hard-to-type constructions,
> just delete the damn thing!
>
> def L

del L

:P

>
> Compare those foolproof 5 chars to what at first did not work right and even
> what did.  And, as other said, in most real applications, you will normalize
> in more than one place. In fact, you may well want a vlen function.
>
> def vlen(seq): return math.sqrt(sum(x*x for x in seq))
>
> --
> Terry Jan Reedy
>
>
> --
> http://mail.python.org/mailman/listinfo/python-list
>



--
Matteo Landi
http://www.matteolandi.net/
From: Lawrence D'Oliveiro on
In message <87k4oah1rp.fsf(a)dpt-info.u-strasbg.fr>, Alain Ketterlin wrote:

> Lawrence D'Oliveiro <ldo(a)geek-central.gen.new_zealand> writes:
>
>> No, I deliberately put it in that order to ensure that the value for l
>> can only ever be evaulated once.
>
> Try this (essentially equivalent to your code):
>
> def f():
> print "hello"
> return 1
>
> V = tuple( 1 for x in [1,2,3] for l in (f(),) )
>
> How many "hello"s do you see?
>
> Comprehension are not loops spelled backwards. The values in:
>
> whatever for i ... for j ...
>
> are the values produced by the equivalent code:
>
> for i ...
> for j ...
> whatever

Damn. I thought that

e for i ... for j ...

was equivalent to

(e for i ...) for j ...

Looks like I was wrong.

From: Bartc on
"Alain Ketterlin" <alain(a)dpt-info.u-strasbg.fr> wrote in message
news:877hkdhyl5.fsf(a)dpt-info.u-strasbg.fr...
> Lawrence D'Oliveiro <ldo(a)geek-central.gen.new_zealand> writes:
>
>> Say a vector V is a tuple of 3 numbers, not all zero. You want to
>> normalize
>> it (scale all components by the same factor) so its magnitude is 1.
>>
>> The usual way is something like this:
>>
>> L = math.sqrt(V[0] * V[0] + V[1] * V[1] + V[2] * V[2])
>> V = (V[0] / L, V[1] / L, V[2] / L)

> Your best bet is to define a function that does the normalization. Your
> (local) name will disappear at the end of the call. If you want it to
> work for any vector size:
>
> def norm(V):
> L = math.sqrt( sum( [x**2 for x in V] ) )
> return [ x/L for x in V ]

There's a cost involved in using those fancy constructions. I found the
following to be about twice as fast, when vectors are known to have 3
elements:

def norm3d(v):
L = math.sqrt((v[0]*v[0]+v[1]*v[1]+v[2]*v[2]))
return (v[0]/L,v[1]/L,v[2]/L)

(Strangely, changing those divides to multiplies made it slower.)

--
Bartc