I am new to python. I have a few questions coming from an armature!
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Thu Aug 18 05:32:37 EDT 2016
On Thursday 18 August 2016 06:25, Terry Reedy wrote:
> On 8/17/2016 2:07 AM, Steven D'Aprano wrote:
>
>> I realise that there are occasions where we might deliberate choose to
>> assign an intermediate value to its own variable, but all else being equal,
>> which would you prefer?
>>
>> #A
>> alist = []
>> alist.append(2)
>> alist.append(4)
>> alist.append(8)
>> process(alist)
[... snip additional examples ...]
> Up to here, #A is a useless and stupid. Have you seen such code written?
As a matter of fact, yes.
Just the other day I posted an example from a former work-mate that was *worse*
than any of those, something like this:
x = []
x.append(1)
x = len(x)
>> #A
>> def callback(btn):
>> return btn.do_the_thing(42) or default
>> the_button.setcommand(callback)
>> process(the_button)
>>
>> #B
>> the_button.setcommand(lambda btn: btn.do_the_thing(42) or default)
>> process(the_button)
>
> This example is *not* parallel to the other 3. Here, A is useful real
> code and might be preferred for multiple reasons.
Sure -- I acknowledged at the beginning that there may be reasons why you want
to give an intermediate value its own variable name.
>> If you find yourself preferring B, B, B, A, you might ask yourself what
>> makes a function different that you prefer to keep temporary functions
>> around where they're not needed.
>
> When 'callback' is set as the command of the button, it is not
> temporary, but must remain as long as the button remains. Only the name
> binding is (possibly) disposable.
The name binding is certainly disposable, because if it wasn't, you couldn't
use an anonymous function (a lambda). *In general*, keeping an additional named
reference to the callback around is unnecessary and wasteful -- although, as
you point out and as I acknowledged, there may be exceptions.
> Beginners often do not understand that the body of a lambda expression
> is evaluated in a new local namespace, and only when the resulting
> function is called, the same as with a def statement. They then neglect
> to capture current values when writing lambda expressions in a for loop.
Sure. But since the behaviour of def functions and lambda functions are
identical, writing a named def won't solve that problem.
> for section_name, line_number in text.parser.toc:
> def goto(line=line_number):
> text.yview(line)
> drop.add_command(label=section_name, command=goto)
>
> To me, this is much better and I intend to commit it. Thank you for
> prodding me to think through how bad the lambda form can be and to
> rewrite the loop so I don't cringe reading it.
The use of a named function here adds next to nothing. Instead of some number
of anonymous functions called "<lambda>", you have an equal number of functions
all named "goto". There's no easy way to distinguish them, and likely no real
need to distinguish them -- they are simple enough that you can be almost
certain that they are correct just from reading the code. So I don't see any
benefit over this:
for section_name, line_number in text.parser.toc:
drop.add_command(label=section_name, command=lambda
line=line_number: text.yview(line))
except that it is easier to fit in 79 columns :-)
--
Steve
More information about the Python-list
mailing list