[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