[Python-ideas] 'where' statement in Python?

Nick Coghlan ncoghlan at gmail.com
Thu Jul 22 14:49:44 CEST 2010

On Thu, Jul 22, 2010 at 5:48 PM, Carl M. Johnson
<cmjohnson.mailinglist at gmail.com> wrote:
> On Wed, Jul 21, 2010 at 6:34 PM, Chris Rebert <pyideas at rebertia.com> wrote:
>> funcs = []
>> for i in range(5):
>>     def f(i=i):
>>        print("#", i)
>>    funcs.append(f)
>> They're all non-obvious idioms, but at least this one is short and
>> easily recognized.
> I actually had to read that twice before I recognized what you had
> done, and I knew to look for something out of the ordinary. That said,
> it *is* the solution GvR recommended as the best solution the last
> time this came up. I just never understood why. To me, if you set
> something as a default value for an argument, it should be because
> it’s a default value, ie. a value that is usually one thing but can
> also be set to something else at the caller’s discretion. I’m just not
> comfortable with using the default value to mean “here’s a value you
> should never change” or “pretty please, don’t pass in an argument,
> because that will screw everything up” or even “I guess you could pass
> in an argument if you wanted to, but that’s not a case I’m really very
> busy thinking about". :-/ But maybe I’m in the minority on this one.

There's a reason that particular trick is called the "default argument hack" :)

The trick is much easier to follow when you *don't* reuse the variable
name in the inner function:

funcs = []
for i in range(5):
    def f(early_bound_i=i):
        print("#", early_bound_i)

Python doesn't really have a good way to request early binding
semantics at this time - the default argument hack is about it.

The given clause (as currently specified in the PEP) forces early
binding semantics on any functions it contains, so it allows you to
write a function definition loop that "does the right thing" with the
following fairly straightforward code:

funcs = []
for i in range(5):
    funcs.append(f) given:
        def f():
            print("#", i)

a) kinda cool
b) veering dangerously close to DWIM* territory (which is not
necessarily a good thing)

Still, the early binding semantics angle is one I had thought about
before - that *is* a genuinely new feature of this proposal. Perhaps
not a hugely compelling one though - I think I've only needed to use
the default argument hack once in the whole time I've been programming


*Don't Worry It's Magic

Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia

More information about the Python-ideas mailing list