![](https://secure.gravatar.com/avatar/d6b9415353e04ffa6de5a8f3aaea0553.jpg?s=120&d=mm&r=g)
On 1/25/2016 1:52 PM, Guido van Rossum wrote:
On Sun, Jan 24, 2016 at 10:32 PM, Terry Reedy <tjreedy@udel.edu> wrote:
What I've concluded from this thread is that function definitions (with direct use 'def' or 'lambda') do not fit well within loops, though I used them there myself.
Right. When you can avoid them, you avoid extra work in an inner loop, which is often a good idea.
When delayed function calls are are needed, what belongs within loops is packaging of a pre-defined function with one or more arguments within a callable. Instance.method is an elegant syntax for doing so. functools.partial(func, args, ...) is a much clumsier generalized expression, which requires an import. Note that 'partial' returns a function for delayed execution even when a complete, not partial, set of arguments is passed.
Right. I've always hated partial() (which is why it's not a builtin) because usually a lambda is clearer (it's difficult to calculate in your head the signature of the thing it returns from the arguments passed), but this is one thing where partial() wins, since it captures values.
I agree that the difficulty of immediately grokking the signature partials that binds arbitrary parameters is a downside to their use. Fake parameters set to a constant necessarily go at the end of the parameter list. The actual signature is the list with those parameters chopped off and ignored. To eliminate the possibility of accidentally supplying a different value positionally, such parameters could (and I think should) be made keyword-only. def f(a, b='default', *, int=int): pass Bound methods necessarily bind the first parameter, often called 'self'. This again makes the actual signature easy to determine.
A major attempted (and tempting) use for definitions within a loop is multiple callbacks for multiple gui widgets, where delayed execution is needed. The three answers to multiple 'why doesn't this work' on both python-list and Stackoverflow are multiple definitions with variant 'default args', a custom make_function function outside the loop called multiple times within the loop, and a direct function outside the loop called with partial within the loop. I am going to start using partial more.
Since writing this, I realized that defining a custom class and using bound methods is a fourth option, which I also like. This binds the differentiating data to an instance, which is then bound to the function, rather than to the function directly. A toy example: ---- import tkinter as tk root = tk.Tk() class Card(tk.Button): hide = 'XXX' def __init__(self, txt): tk.Button.__init__(self, root, text=self.hide) # or # super().__init__(root, text=self.hide) self.txt = txt self.exposed = False def flip(self): self['text'] = self.hide if self.exposed else self.txt self.exposed = not self.exposed for i, txt in enumerate(('one', 'two')): card = Card(txt) card['command'] = card.flip card.grid(row=0, column=i) #root.mainloop() # uncomment if run on command line without -i ---- The main problem with this is that some beginners are trying to write (or being told to write) tkinter guis before they learn about class statements. The super() form is easier to write, but its use is even more 'advanced'. -- Terry Jan Reedy