Explanation of this Python language feature? [x for x in x for x in x] (to flatten a nested list)
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Mon Mar 24 21:45:02 EDT 2014
On Mon, 24 Mar 2014 14:47:11 -0500, Mark H Harris wrote:
> On 3/24/14 4:49 AM, Steven D'Aprano wrote:
>> There's no doubt that lambda is less-often useful than is the def
>> statement. But not only is it still useful, but there is a continual
>> stream of people asking for Python to make it *more useful* by allowing
>> the body of a lambda to be a full block, not just a single statement.
>> Guido has stated (although I cannot remember where, so cannot paste a
>> link) that he accepts that in principle, so long as somebody comes up
>> with acceptable syntax.
>
> Now, this will seem strange to you, but if lambda were expanded to
> include an entire block, well now, I would know two things:
> 1) python has commitment to lambda
Python has a commitment to lambda. lambda is not going anywhere. There
was some idea chatter five or six years ago about dropping it from the
language. It didn't get dropped, so now it is as much a part of the
language as for-loops, print, classes and import.
> and 2) lambda would become WAY more useful...
Every one agrees that being able to include a full suite of statements in
an expression form would be useful. Unfortunately, due to the constraint
of Python's syntax, it seems to be impossible. People have looked for 20+
years, and nobody has come up with an acceptable syntax.
[...]
>>> Lambda is a problem of confusion for scientists and other
>>> mathematicians (amateur and otherwise) {snip}
>>{snip}
>> But nor should the confusion of somebody who doesn't know the language
>> count for much.
>
> This is the main disagreement between the two of us on this topic.
> It should count for TONS; whole metric TONs. Because someone who
> understands python primarily, and after five years of coding (say me)
> somebody tells (me) to use lambda in a key clause so that my sort will
> work, or work better, or work "their" way; and I have no idea why I need
> this nameless function (after I find out that "that" is what it is!)
Then you don't understand *sorting*. If you don't understand why you need
a key function, the problem is not the syntax used to create the key
function, but your understanding of sort. Time to remove sorting from
Python, yes? No?
It's not lambda that is giving you trouble. That's just syntax. There is
no conceptual difference between:
data.sort(key=lambda item: *magic goes on here*)
and
def key_func(item):
*magic goes on here*
data.sort(key=key_func)
If the first confuses you, so will the second. If you are capable of
learning what the first means, learning the second is no harder.
> Its confusing, and please contrast between complicated. I don't mind
> complicated, or extensive, or even hard, but when something is
> needlessly confusing, then why?
I don't know why you insist it is confusing. Maybe you're just no good at
seeing the correspondence between
lambda x: expression
and
def func(x):
return expression
>> Python's ints don't work exactly the same as ints do in some other
>> languages, nor do Python's strings, nor is Python's object model
>> precisely the same as that of some other languages. I think that it
>> would be a ridiculous idea to discard int, str and the entire object
>> system just because some people are surprised that Python doesn't
>> behave exactly like some other language. I don't think lambda is any
>> different.
>
> Your logic is faulty here. Conceptually python's lambda doesn't
> work as expected, from contexts that define lambda
Python defines lambda too. Why should Python have to bend over to suit
the definition used by other languages? They don't own the concept of
anonymous functions. Anonymous functions are found in all sorts of
languages, with different semantics and different syntax:
Pike: lambda(typ1 para1, typ2, para2, ...) { ... };
Perl: sub { my ($a, $b) = @_; ... }
Smalltalk: [:a :b| ... ]
Haskell: \a b -> ...
Erlang: fun(a, b) -> ... end
Dylan: method(a, b) ... end method
to mention just a few. Ruby even has at least three ways of spelling
lambda, one of which even uses the word lambda:
{|a, b| ... }
lambda {|a, b| ...}
proc {|a, b| ...}
> and where lambda in functional programming is VERY important.
And? Nobody is saying that they have to stop using the term lambda.
Certainly I'm not. I wouldn't be so rude.
> For one thing, why would we
> want to "spell out" the word "lambda". ( \x y -> x + y ) a b ) If
> we're going to use lambda, then use it.
So you don't like the syntax of Python's lambda. That's your prerogative.
But frankly, one thing I dislike about Haskell is that it is too terse.
Why would you use lambda without spelling out explicitly that you are
doing so?
>> Other languages -- not even Lisp -- don't get to be the sole decider as
>> to what counts as an anonymous function. Python's lambda may be
>> limited, but it is a perfectly fine lambda for what it is intended to
>> do.
>
> Is that the same as George W. Bush's "decider" ?
I have no idea why you are mocking my use of the word "decider". It's a
perfectly legitimate word, a standard term in English for someone who
decides. The Oxford dictionary dates it back to sometime between 1670 and
1699, so it is hardly a neologism or one of Junior Bush's malapropisms.
Let me put it another way. Functional programming languages do not get to
be the sole decision-maker of what counts as a legitimate syntax or
semantics for anonymous functions.
> I agree, and so does the link I referenced, for what it was designed
> to do, its powerful; esp if one needs to embed a function in an
> expression; that is what lambda is for.
Right.
>>> Its also confusing to sophisticated users of all stripes who may not
>>> be aware of "lambda" at all.
>>
>> If they're not aware of lambda, how are they confused by it?
>
> See above. They are recommended its use (maybe on this list) and
> they just don't get it; because its unnecessarily confusing.
Then they are aware of lambda.
Confusing in what way? Is it the keyword used? You don't need to know the
background of the term to learn to use it. If non-English speakers can
memorise that you use "class" to define classes, English speakers can
stop being so precious and memorise that "lambda" is used to define a
function in an expression.
'lambda' is just one of those jargon words, like 'tuple', 'iterate',
'boolean', 'closure', ... just learn it, and you'll be fine. If you want
to investigate the background of the word, go right ahead, but it won't
make you a better programmer to know that "boolean" is named after George
Boole, and I still have no idea what the origin of "tuple" is. (And after
15+ years I still want to spell it "turple".)
[...]
> Programming should be a
> liberal art available to everyone in the set of all "normal" educated
> people.
Why should it be? Programming is no more a liberal art than painting is
an offshoot of calculus.
Most "normal" (normal as defined by whom?) educated people have no
interest, no desire, and no aptitude for programming. Most *programmers*
have no aptitude for the rigor of programming -- the world is full of
lousy programmers churning out their 40 lines of buggy VB/PHP/Java/C code
per day but aren't any good at it:
http://www.yacoset.com/Home/signs-that-you-re-a-bad-programmer
http://haacked.com/archive/2007/02/27/Why_Cant_Programmers._Read.aspx/
Programming is a skill, like writing iambic pentameter. Should liberal
arts courses ban the use of iambic pentameter by poets because some
people find it confusing and can't count syllables or tell the difference
between stressed and unstressed? (I know I can't. My wife despairs that I
am so useless at anything like poetry.)
> Some developers (themselves perhaps with degrees Ph.D. in
> mathematics or computer science) forget about the fact that "normal"
> educated people want to leverage their computer (maybe with python) for
> problem solution without having to become a professional computer
> scientist. I am advocating for those people.
So you say. But I think you are actually being terribly condescending and
elitist at the same time. Consider:
(1) People who just want to get the job done, without learning a bunch of
theory, *won't care* how their sort key function is written. They're
looking for a recipe that they can copy and paste, and whether you write
it like this:
data.sort(key=lambda item: item[1])
or like this:
from operator import itemgetter
data.sort(key=itemgetter(1))
or like this:
def sort_key(item):
return item[1]
data.sort(key=sort_key)
*they won't care*. In fact, they'll probably prefer the first version,
with lambda, because it is fewer lines to copy.
And this is okay. Sometimes you've got more important things to do than
understand how every line of your code works, especially for throw-away
code, you just want to use it. It is very elitist to insist that features
that some people don't understand have to go. Do you understand how
import works? I bet you don't. It's so complicated that there are
probably only one or two core developers who really understand it in all
it's glory. You just use it: "import this", and it just works. lambda is
the same.
Sometimes programming is just a means to an end and the programmer just
wants an answer now.
(2) You're concluding that just because somebody is confused by lambda,
they would be better off if lambda was removed. That's horribly
patronising. Have you considered that maybe they will take that as an
opportunity to *learn something new*? That they'll learn how to use
lambda, they may even investigate the theory behind it?
I am especially aggravated by your attack on lambda because I was that
person. I had never heard of lambda calculus. When I first learned
Python, lambda's syntax troubled me for a while. I had to keep looking it
up, until suddenly the penny dropped that the argument list is exactly
the same as the argument list of def. Replace "def name" with "lambda",
drop the brackets, and use a single expression without "return", and
Joan's your Auntie.
But I learned it, and it got me interested in where the name came from,
and I discovered the lambda calculus and decided that while I have every
admiration for the people who fly that high into the rarefied air of
theory, that's not an area I have much interest in. In any case, I am a
better programmer -- or at least a more educated one -- precisely because
Python didn't dumb down, it didn't patronise me, it offered an
"advanced" (huh! not really) feature that I otherwise would never have
been exposed to.
Yes, Python could remove lambda, and take that opportunity away from
others. Python would be a lesser language for it, and Python programmers
will be lesser programmers for it.
Python programmers are some of most widely read programmers around,
compared to the average C or PHP or VB coder. That's because they are
exposed to so many different concepts in the language. Not everyone cares
to learn about them, and that's okay, but they aren't Python's core
audience.
>> You want to remove lambda because it causes confusion. Okay, for the
>> sake of the argument I will agree that lambda is confusing. Do you know
>> what else is confusing?
>
> I don't want to remove anything at this point. I am only suggesting
> that over time the python community might evaluate whether the lambda
> (map, filter, reduce) thing is a language benefit. If so, manet in
> aeternum. Elif, deprecate it and over time phase it out completely. Its
> a community decision of course, and I'm NOT demanding anything.
This discussion was held five years ago. And lambda is still here.
>> Threading is confusing. So is multiprocessing. So are databases.
>> Unicode is confusing. First-class functions are confusing. Recursion is
>> confusing. Closures are confusing. List comprehensions are confusing.
>> What the hell are trampolines? I'm certainly confused by them.
>
> Argument by analogy almost never works. Please don't confuse my word
> "confusing" with your interpretation "complicated". Actually, I do not
> find any of those above mentioned as "confusing,"
Good for you! I mean it, I'm not being sarcastic. But I *know* people
find all those things confusing, because (1) either I found, or still do,
find them confusing, or (2) because I've seen people confused by them.
When I say "confusing", I mean it. I don't mean complicated.
> while I do admit they
> are complicated--even extremely complicated. An intelligent person
> educated in the liberal arts should be able to sit down over time and
> pick-up the concepts in a new area--without--being confused by the
> material or presentation. Lambda is confusing NOT because its
> complicated (because its not) but because 1) it does not work like other
> lambda concepts in functional programming,
Do you really believe that people educated in the liberal arts are
exposed to the lambda calculus? Most MATHEMATICIANS aren't exposed to
lambda calculus.
> and 2) because the syntax
> does not lend itself easily to immediate interpretation (by normal
> people) nor does it lend itself easily to explanation even in the best
> effort.
I think that's just nonsense. Take a one-line function:
def func(args):
return stuff
Remove the "def func", the brackets, and the "return". Move it all to one
line, and stick the magic word "lambda" at the front:
lambda args: stuff
And you're done. That's all there is to it.
Your insistence that lambda is confusing is awfully condescending. People
are not as dumb as you insist, and they are perfectly capable of learning
lambda without a comp sci degree. Like any technical jargon, there is
vocabulary and meaning to learn, but the concept is no more difficult
than ordinary def functions.
--
Steven D'Aprano
http://import-that.dreamwidth.org/
More information about the Python-list
mailing list