[Python-ideas] Respectively and its unpacking sentence
Steven D'Aprano
steve at pearwood.info
Wed Jan 27 19:12:51 EST 2016
On Wed, Jan 27, 2016 at 12:25:05AM -0500, Mirmojtaba Gharibi wrote:
> Hello,
>
> I'm thinking of this idea that we have a pseudo-operator called
> "Respectively" and shown maybe with ;
>
> Some examples first:
>
> a;b;c = x1;y1;z1 + x2;y2;z2
Regardless of the merits of this proposal, the suggested syntax cannot
be used because that's already valid Python syntax equivalent to:
a
b
c = x1
y1
z1 + x2
y2
z2
So forget about using the ; as that would be ambiguous.
[...]
> Then there is another unpacking operator which maybe we can show with $
> sign and it operates on lists and tuples and creates the "Respectively"
> version of them.
> So for instance,
> vec=[]*10
> $vec = $u + $v
> will add two 10-dimensional vectors to each other and put the result in vec.
[]*10 won't work, as that's just []. And it seems very unpythonic to
need to pre-allocate a list just to do vectorized addition.
I think you would be better off trying to get better support for
vectorized operations into Python:
vec = add(u, v)
is nearly as nice looking as u + v, and it need not even be a built-in.
It could be a library.
In an earlier version of the statistics module, I experimented with
vectorized functions for some of the operations. I wanted a way for
the statistics functions to *automatically* generate either scalar or
vector results without any extra programming effort.
E.g. writing mean([1, 2, 3]) would return the scalar 2, of course,
while:
mean([(1, 10, 100),
(2, 20, 200),
(3, 30, 300)])
would operate column-wise and return (2, 20, 200). To do that, I needed
vectorized versions of sum, division, sqrt etc. I didn't mind if they
were written as function calls instead of operators:
divide(6, 3) # returns 2
divide((6, 60, 600), 3) # returns (2, 20, 200)
which I got with a function:
divide = vectorize(operator.truediv)
where vectorize() took a scalar operator and returned a function that
looped over two vectors and applied the operator to each argument in an
elementwise fashion. I eventually abandoned this approach because the
complexity and performance hit of my initial implementation was far too
great, but maybe that was just my poor implementation.
I think that vectorized functions would be very useful in Python.
Performance need not be super-fast -- numpy, numba, and the other
heavy-duty third-party tools would continue to dominate the
high-performance scientific computing niche, but they should be at least
*no worse* than the equivalent code using a loop.
If you had a vectorized add() function, your example:
a;b;c = x1;y1;z1 + x2;y2;z2
would become:
a, b, c = add([x1, y1, z1], [x2, y2, z2])
Okay, it's not as *nice looking* as the + operator, but it will do. Or
you could subclass list to do this instead of concatenation.
I would support the addition of a vectorize() function which took an
arbitrary scalar function, and returned a vectorized version:
func = vectorized(lambda x, y: 2*x + y**3 - x*y/3)
a, b, c = func(vector_x, vector_y)
being similar to:
f = lambda x, y: 2*x + y**3 - x*y/3
a, b, c = [f(x, y) for x, y in zip(vector_x, vector_y)]
[...]
> For example, we can calculate the inner product between two vectors like
> follows (inner product is the sum of component wise multiplication of two
> vectors):
>
> innerProduct =0
> innerProduct += $a * $b
>
> which is equivalent to
> innerProduct=0
> for i in range(len(a)):
> ...innerProduct += a[i]+b[i]
def mult(*vectors):
for t in zip(*vectors):
yield reduce(operator.mul, t)
innerProduct = sum(mult(a, b))
--
Steve
More information about the Python-ideas
mailing list