Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #58875 > unrolled thread
| Started by | Peter Cacioppi <peter.cacioppi@gmail.com> |
|---|---|
| First post | 2013-11-08 14:22 -0800 |
| Last post | 2013-11-10 16:00 -0800 |
| Articles | 15 — 5 participants |
Back to article view | Back to comp.lang.python
my favorite line of py code so far Peter Cacioppi <peter.cacioppi@gmail.com> - 2013-11-08 14:22 -0800
Re: my favorite line of py code so far Chris Angelico <rosuav@gmail.com> - 2013-11-09 09:32 +1100
Re: my favorite line of py code so far Peter Cacioppi <peter.cacioppi@gmail.com> - 2013-11-08 14:43 -0800
Re: my favorite line of py code so far Peter Otten <__peter__@web.de> - 2013-11-09 08:12 +0100
Re: my favorite line of py code so far Peter Cacioppi <peter.cacioppi@gmail.com> - 2013-11-09 01:23 -0800
Re: my favorite line of py code so far Chris Angelico <rosuav@gmail.com> - 2013-11-09 20:28 +1100
Re: my favorite line of py code so far Paul Rubin <no.email@nospam.invalid> - 2013-11-09 01:49 -0800
Re: my favorite line of py code so far Peter Otten <__peter__@web.de> - 2013-11-09 12:49 +0100
Re: my favorite line of py code so far Stefan Behnel <stefan_ml@behnel.de> - 2013-11-09 13:41 +0100
Re: my favorite line of py code so far Chris Angelico <rosuav@gmail.com> - 2013-11-09 23:45 +1100
Re: my favorite line of py code so far Peter Otten <__peter__@web.de> - 2013-11-09 14:49 +0100
Re: my favorite line of py code so far Peter Cacioppi <peter.cacioppi@gmail.com> - 2013-11-10 00:57 -0800
Re: my favorite line of py code so far Chris Angelico <rosuav@gmail.com> - 2013-11-10 21:23 +1100
Re: my favorite line of py code so far Peter Cacioppi <peter.cacioppi@gmail.com> - 2013-11-10 00:59 -0800
Re: my favorite line of py code so far Peter Cacioppi <peter.cacioppi@gmail.com> - 2013-11-10 16:00 -0800
| From | Peter Cacioppi <peter.cacioppi@gmail.com> |
|---|---|
| Date | 2013-11-08 14:22 -0800 |
| Subject | my favorite line of py code so far |
| Message-ID | <fbbabb45-f0e3-4e7f-968f-9822607c450a@googlegroups.com> |
my fav so far is this _ = lambda c : lambda x : c(*x) c can be any calleable and x any iterable, but I tend to use it with a class, and then map _(class) over the result of a zip. It must be in the library somewhere, but I haven't found it. I'm never sure what to call it, so I just reroll it into _ as needed. It's pretty easy for me to remember, but I'll probably tattoo it on my chest just in case.
[toc] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-11-09 09:32 +1100 |
| Message-ID | <mailman.2265.1383949984.18130.python-list@python.org> |
| In reply to | #58875 |
On Sat, Nov 9, 2013 at 9:22 AM, Peter Cacioppi <peter.cacioppi@gmail.com> wrote: > my fav so far is this > > _ = lambda c : lambda x : c(*x) > > c can be any calleable and x any iterable, but I tend to use it with a class, and then map _(class) over the result of a zip. > > It must be in the library somewhere, but I haven't found it. I'm never sure what to call it, so I just reroll it into _ as needed. It's pretty easy for me to remember, but I'll probably tattoo it on my chest just in case. So... for any given class, it returns a tweaked version that unpacks an iterable of its arguments instead of taking separate args. Interesting, perhaps, but not something that'll be needed in the stdlib. But as a demo of how easily Python primitives can be combined into some fairly elegant code, I think this is as good as any! ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Peter Cacioppi <peter.cacioppi@gmail.com> |
|---|---|
| Date | 2013-11-08 14:43 -0800 |
| Message-ID | <022fa92a-a502-4af4-9928-8f15836e0881@googlegroups.com> |
| In reply to | #58875 |
Chris said: "So... for any given class, it returns a tweaked version that unpacks an iterable of its arguments instead of taking separate args. " It works with any calleable (not just any class), but otherwise your summary is spot on. "Interesting, perhaps, but not something that'll be needed in the stdlib." Fair enough. In the interest of self promotion, I'm calling it the Cacioppi combinator. The tattoo apt is for Tues.
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2013-11-09 08:12 +0100 |
| Message-ID | <mailman.2279.1383981142.18130.python-list@python.org> |
| In reply to | #58875 |
Peter Cacioppi wrote:
> my fav so far is this
>
> _ = lambda c : lambda x : c(*x)
>
> c can be any calleable and x any iterable, but I tend to use it with a
> class, and then map _(class) over the result of a zip.
>
> It must be in the library somewhere, but I haven't found it. I'm never
> sure what to call it, so I just reroll it into _ as needed. It's pretty
> easy for me to remember, but I'll probably tattoo it on my chest just in
> case.
You mean
>>> class P:
... def __init__(self, x, y):
... self.x = x
... self.y = y
... def __repr__(self):
... return "Point(x={0.x}, y={0.y})".format(self)
...
>>> P(1, 2)
Point(x=1, y=2)
>>> _ = lambda c: lambda x: c(*x)
>>> list(map(_(P), zip([1,2,3], [6, 5, 4])))
[Point(x=1, y=6), Point(x=2, y=5), Point(x=3, y=4)]
? While the obvious approach would be
>>> [P(*args) for args in zip([1,2,3], [6, 5, 4])]
[Point(x=1, y=6), Point(x=2, y=5), Point(x=3, y=4)]
there is also itertools.starmap():
>>> from itertools import starmap
>>> list(starmap(P, zip([1,2,3], [6, 5, 4])))
[Point(x=1, y=6), Point(x=2, y=5), Point(x=3, y=4)]
[toc] | [prev] | [next] | [standalone]
| From | Peter Cacioppi <peter.cacioppi@gmail.com> |
|---|---|
| Date | 2013-11-09 01:23 -0800 |
| Message-ID | <729e093a-6312-44dc-8ed4-1dd5ea344066@googlegroups.com> |
| In reply to | #58875 |
Peter Otten said: ">>> _ = lambda c: lambda x: c(*x) >>> list(map(_(P), zip([1,2,3], [6, 5, 4]))) [Point(x=1, y=6), Point(x=2, y=5), Point(x=3, y=4)] ? While the obvious approach would be >>> [P(*args) for args in zip([1,2,3], [6, 5, 4])] [Point(x=1, y=6), Point(x=2, y=5), Point(x=3, y=4)] " I would have coded >>> map(_(P), zip([1,2,3], [6, 5, 4])) Which is very concise and (to me) quite clear. Forgive me for having a bias for fewer characters. Are you saying it's always preferable to avoid map? Is map going to be deprecated? I sometimes use map, sometimes comprehensions. I suspect other people do the same, that's why the language supports map and comprehensions. "there is also itertools.starmap(): " Thanks, that's a bit closer to what I am doing. To me the pure combinator is more appealing than starmap, but the presence of starmap explains why the library wouldn't need the combinator.
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-11-09 20:28 +1100 |
| Message-ID | <mailman.2286.1383989316.18130.python-list@python.org> |
| In reply to | #58921 |
On Sat, Nov 9, 2013 at 8:23 PM, Peter Cacioppi <peter.cacioppi@gmail.com> wrote: > I sometimes use map, sometimes comprehensions. I suspect other people do the same, that's why the language supports map and comprehensions. I think map is fine if you can use a named function, but if you can't come up with a descriptive name for what you're doing, a comprehension is probably better (as it'll have the code right there). Mapping _ across everything tells you nothing about what it's actually doing. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2013-11-09 01:49 -0800 |
| Message-ID | <7x61s1aorb.fsf@ruckus.brouhaha.com> |
| In reply to | #58921 |
Peter Cacioppi <peter.cacioppi@gmail.com> writes: >>>> [P(*args) for args in zip([1,2,3], [6, 5, 4])] [P(x,y) for x,y in zip(...)] > Are you saying it's always preferable to avoid map? Not always. Depends on context, partly subjective. > I sometimes use map, sometimes comprehensions. I suspect other people > do the same, that's why the language supports map and comprehensions. Comprehensions came along later and there was some noise made about eliminating map for a while, though I think that's died down. > "there is also itertools.starmap(): " > Thanks, that's a bit closer to what I am doing. To me the pure > combinator is more appealing than starmap, You could look at the functools module too, particularly functools.partial. For that matter, you could also try Haskell. It's even more concise, and this flavor of code is easier to keep reliable when there's compile-time type checking.
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2013-11-09 12:49 +0100 |
| Message-ID | <mailman.2288.1383997830.18130.python-list@python.org> |
| In reply to | #58921 |
Peter Cacioppi wrote:
> Peter Otten said:
>
>
> ">>> _ = lambda c: lambda x: c(*x)
>>>> list(map(_(P), zip([1,2,3], [6, 5, 4])))
> [Point(x=1, y=6), Point(x=2, y=5), Point(x=3, y=4)]
>
> ? While the obvious approach would be
>
>>>> [P(*args) for args in zip([1,2,3], [6, 5, 4])]
> [Point(x=1, y=6), Point(x=2, y=5), Point(x=3, y=4)] "
>
> I would have coded
>>>> map(_(P), zip([1,2,3], [6, 5, 4]))
>
> Which is very concise and (to me) quite clear. Forgive me for having a
> bias for fewer characters.
Consider developing a bias for self-explanatory names ;)
> Are you saying it's always preferable to avoid map?
No. I'm saying that if you have a problem with multiple solutions you should
pick the boringly obvious one if you plan to reuse or publish the code.
There is no obvious meaning attached to _ -- so don't use it.
> Is map going to be deprecated?
Not to my knowledge. I use it when I already have a function ready
to be called with the items in a sequence. Continuing the Point example that
could be
map(Point, xvals, yvals)
or
map(Point.from_tuple, xypairs)
> I sometimes use map, sometimes comprehensions. I suspect other people do
> the same, that's why the language supports map and comprehensions.
>
> "there is also itertools.starmap(): "
>
> Thanks, that's a bit closer to what I am doing. To me the pure combinator
> is more appealing than starmap, but the presence of starmap explains why
> the library wouldn't need the combinator.
I found only a single use of starmap on my machine (and one more in the
stdlib)
# in redis.client
all_cmds = ''.join(starmap(connection.pack_command,
[args for args, options in commands]))
and frankly, I would prefer
all_cmds = "".join(
connection.pack_command(*args) for args, options in commands)
which by some strange coincidence also requires fewer letters to type.
[toc] | [prev] | [next] | [standalone]
| From | Stefan Behnel <stefan_ml@behnel.de> |
|---|---|
| Date | 2013-11-09 13:41 +0100 |
| Message-ID | <mailman.2289.1384000887.18130.python-list@python.org> |
| In reply to | #58921 |
Peter Otten, 09.11.2013 12:49:
> There is no obvious meaning attached to _ -- so don't use it.
Not quite true. Depending on the context, the obvious meanings of "_" in
Python are either
1) "ignore me", e.g. in
_, b = some_tuple
or
2) "this is a non-public thing", as in
class Xyz:
_private = 1
or
3) "I am the translation function", as commonly used in (HTML) templates:
_("translation key here")
None of the three meanings applies to the OP's example, AFAICT.
Stefan
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-11-09 23:45 +1100 |
| Message-ID | <mailman.2290.1384001149.18130.python-list@python.org> |
| In reply to | #58921 |
On Sat, Nov 9, 2013 at 11:41 PM, Stefan Behnel <stefan_ml@behnel.de> wrote: > 2) "this is a non-public thing", as in > > class Xyz: > _private = 1 Your three meanings all have the etymology of "ignore me", but I would distinguish this one from the others. An underscore used on its own has meaning; an underscore as part of a larger token has quite different meaning, and can have any of several - "private-ish" (as above), "mangle me" (double leading, no trailing), "magic" (dunder - double leading/double trailing), and "word separator" (between_multiple_words_in_an_identifier). Your other two examples are what we're talking about here, though. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2013-11-09 14:49 +0100 |
| Message-ID | <mailman.2296.1384004974.18130.python-list@python.org> |
| In reply to | #58921 |
Stefan Behnel wrote:
> Peter Otten, 09.11.2013 12:49:
>> There is no obvious meaning attached to _ -- so don't use it.
>
> Not quite true. Depending on the context, the obvious meanings of "_" in
> Python are either
>
> 1) "ignore me", e.g. in
>
> _, b = some_tuple
>
> or
>
> 2) "this is a non-public thing", as in
>
> class Xyz:
> _private = 1
>
This doesn't fit the bill provided we're discussing the name _ rather than
any underscore.
>
> 3) "I am the translation function", as commonly used in (HTML) templates:
>
> _("translation key here")
>
>
> None of the three meanings applies to the OP's example, AFAICT.
I can come up with one more, the last non-None result calculated in the
interactive interpreter,
>>> 2*2
4
>>> _
4
so we're back to three. All seem to be established conventions rather than
obvious choices.
[toc] | [prev] | [next] | [standalone]
| From | Peter Cacioppi <peter.cacioppi@gmail.com> |
|---|---|
| Date | 2013-11-10 00:57 -0800 |
| Message-ID | <dae981ac-14e7-47c8-89ed-a5ad21e956ca@googlegroups.com> |
| In reply to | #58875 |
Chris said : "I think map is fine if you can use a named function, but if you can't come up with a descriptive name for what you're doing, a comprehension is probably better (as it'll have the code right there). Mapping _ across everything tells you nothing about what it's actually doing" OK, this makes a lot of sense. (Any my apologies to Peter Otten if my previous post was overly snarky). How about this? I put the following in my catchall_utility.py module # the oneArg combinator takes a multi-argument calleable # and returns the equivalent single argument calleable oneArg = lambda c: lambda x : c(*x) With example code map(oneArg(P), zip([1,2,3], [6, 5, 4])) To my mind the idea that oneArg(P) is a calleble that behaves exactly like P, with the only difference being oneArg(P) accepts P's arguments packed into a single iterable, is very intuitive. I actually find the oneArg version more readable than the comprehension that unpacks explicitly using *. At this point I probably have equal experience coding Lisp and Py, with the latter more recent, so I don't think this bias can be chalked up to "experienced functional programmer, beginner py programmer". To be clear, I was never really intending to keep the _ = lambda c : lambda x : c(*x) map(oneArg(P), zip([1,2,3], [6, 5, 4])) code snippets in my final work product. The purpose of this thread was too fish around for ideas on what to replace it with when I execute the "use the unit tests to facilitate refactoring for better names and more professional idioms" step. (We never, ever, skip that step, right?) Although it is unlikely you will convince me to use the comprehension in this sort of situation, it's possible someone could convince me to use starmap with P instead of map with oneArg(P). Those two techniques are fully equivalent. But, to my mind, the latter just feels right, and I find that I write fewer bugs when I use idioms that resonate. Thanks again, good thread for me
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-11-10 21:23 +1100 |
| Message-ID | <mailman.2328.1384079035.18130.python-list@python.org> |
| In reply to | #58993 |
On Sun, Nov 10, 2013 at 7:57 PM, Peter Cacioppi <peter.cacioppi@gmail.com> wrote: > Chris said : > > "I think map is fine if you can use a named function, but if you can't > come up with a descriptive name for what you're doing, a comprehension > is probably better (as it'll have the code right there). Mapping _ > across everything tells you nothing about what it's actually doing" > > How about this? I put the following in my catchall_utility.py module > > # the oneArg combinator takes a multi-argument calleable > # and returns the equivalent single argument calleable > oneArg = lambda c: lambda x : c(*x) Now it has a name, so I could imagine you importing it into modules and using it usefully. I'd be inclined to call it something along the lines of "unpacked" but that's just bikeshedding. > ... I find that I write fewer bugs when I use idioms that resonate. Absolutely! The unfortunate truth, though, is that idioms that resonate with you _and nobody else_ are just as big a problem as bugs, because they're unmaintainable. So hopefully what you're doing will make sense to other people too! ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Peter Cacioppi <peter.cacioppi@gmail.com> |
|---|---|
| Date | 2013-11-10 00:59 -0800 |
| Message-ID | <3b7385e0-da4b-4482-ac62-904d3a624546@googlegroups.com> |
| In reply to | #58875 |
Sorry, typo, meant to say To be clear, I was never really intending to keep the _ = lambda c : lambda x : c(*x) map(_(P), zip([1,2,3], [6, 5, 4])) code snippets in my final work product. The purpose of this thread was too fish around for ideas on what to replace it with...
[toc] | [prev] | [next] | [standalone]
| From | Peter Cacioppi <peter.cacioppi@gmail.com> |
|---|---|
| Date | 2013-11-10 16:00 -0800 |
| Message-ID | <71b09c61-85b3-4c47-8dab-c27e6fe13dbb@googlegroups.com> |
| In reply to | #58875 |
Chris said : "Absolutely! The unfortunate truth, though, is that idioms that resonate with you _and nobody else_ are just as big a problem as bugs, because they're unmaintainable. So hopefully what you're doing will make sense to other people too! " There is some truth in what you say ... but in this case we're talking about an algorithmically trivial portion of a project for which I am basically BDFL. So as long as I'm not totally in left field, I'm going with what feels truthy to me. Also, lambda c : lambda x : c(*x) would make a sweet tattoo. Much better than some Kanji that might as well translate into "dumb white guy" for all I know ;)
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web