<div dir="ltr"><div>I accidentally replied only to Steven - sorry! - this is what I said, with a typo corrected: </div><div><br></div>> a_list_of_strings..lower()<div>> </div><div>> str.lower.(a_list_of_strings)</div><div><br></div><div>I much prefer this solution to any of the other things discussed so far. I wonder, though, would it be general enough to simply have this new <font face="monospace, monospace">'.'</font> operator interact with <font face="monospace, monospace">__iter__</font>, or would there have to be new magic methods like <font face="monospace, monospace">__veccall__</font>, <font face="monospace, monospace">__vecgetattr__</font>, etc? Would a single <font face="monospace, monospace">__vectorize__ </font>magic method be enough?</div><div><br></div><div>For example, I would expect <font face="monospace, monospace">(1, 2, 3) .** 2</font> to evaluate as a tuple and <font face="monospace, monospace">[1, 2, 3] .** 2</font> to evaluate as a list, and <font face="monospace, monospace">some_generator() .** 2</font> to still be a generator.</div><div><br></div><div>If there were a <font face="monospace, monospace">__vectorize__(self, func) </font> which returned the iterable result of applying func on each element of self:</div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">class list:</font></div><div><font face="monospace, monospace"> def __vectorize__(self, func):</font></div><div><font face="monospace, monospace"> return [func(e) for e in self]</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">some_list .* other becomes some_list.__vectorize__(lambda e: e * 2)</font></div><div><font face="monospace, monospace">some_string..lower() becomes some_string.__vectorize__(str.lower)</font></div><div><font face="monospace, monospace">some_list..attr becomes some_list.__vectorize__(operator.__attrgetter__('attr'))</font></div><div><br></div><div>Perhaps there would be a better name for such a magic method, but I believe it would allow existing sequences to behave as one might expect, but not require each operator to require its own definition. I might also be over-complicating this, but I'm not sure how else to allow different sequences to give results of their same type.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jan 31, 2019 at 6:24 PM Steven D'Aprano <<a href="mailto:steve@pearwood.info">steve@pearwood.info</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Thu, Jan 31, 2019 at 09:51:20AM -0800, Chris Barker via Python-ideas wrote:<br>
<br>
> I do a lot of numerical programming, and used to use MATLAB and now numpy a<br>
> lot. So I am very used to "vectorization" -- i.e. having operations that<br>
> work on a whole collection of items at once.<br>
[...]<br>
> You can imagine that for more complex expressions the "vectorized" approach<br>
> can make for much clearer and easier to parse code. Also much faster, which<br>
> is what is usually talked about, but I think the readability is the bigger<br>
> deal.<br>
<br>
Julia has special "dot" vectorize operator that looks like this:<br>
<br>
L .+ 1 # adds 1 to each item in L<br>
<br>
func.(L) # calls f on each item in L<br>
<br>
<a href="https://julialang.org/blog/2017/01/moredots" rel="noreferrer" target="_blank">https://julialang.org/blog/2017/01/moredots</a><br>
<br>
The beauty of this is that you can apply it to any function or operator <br>
and the compiler will automatically vectorize it. The function doesn't <br>
have to be written to specifically support vectorization.<br>
<br>
<br>
> So what does this have to do with the topic at hand?<br>
> <br>
> I know that when I'm used to working with numpy and then need to do some<br>
> string processing or some such, I find myself missing this "vectorization"<br>
> -- if I want to do the same operation on a whole bunch of strings, why do I<br>
> need to write a loop or comprehension or map? that is:<br>
> <br>
> [s.lower() for s in a_list_of_strings]<br>
> <br>
> rather than:<br>
> <br>
> a_list_of_strings.lower()<br>
<br>
Using Julia syntax, that might become a_list_of_strings..lower(). If you <br>
don't like the double dot, perhaps str.lower.(a_list_of_strings) would <br>
be less ugly.<br>
<br>
<br>
<br>
-- <br>
Steven<br>
_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/codeofconduct/</a><br>
</blockquote></div>