syntax for code blocks

Steven D'Aprano steve+comp.lang.python at pearwood.info
Thu May 3 23:47:36 EDT 2012


On Thu, 03 May 2012 19:44:57 -0700, alex23 wrote:

[snip]
> My version was:
> 
>     def a(): pass
>     def b(): pass
> 
>     func_packet = locals()
>     func(arg, func_packet)
> 
> Now, please explain how that produces name-clashes that your version
> does not.

I too am uncomfortable about passing locals() to a function, but not 
because of imaginary "name clashes". The problem as I see it is that this 
will give the function access to things the function has no need for.

While CPython doesn't allow the called function to rebind names in the 
local scope (except in the case where the local scope is also the global 
scope), that may not apply to all Python implementations. So code which 
works safely in CPython may break badly in some other implementation.

Another problem is that even in implementations where you can't rebind 
locals, the called function might mutate them instead. If any of the 
content of locals() are mutable, you're giving the function the potential 
to mutate them, whether it needs that power or not.

Let me put it this way... suppose you had a function with a signature 
like this:

def spam(a, b, c, **kwargs):
    ...


and you knew that spam() ignores keyword arguments that it doesn't need. 
Or at least is supposed to. Suppose you needed to make this call:

spam(23, 42, ham=None, cheese="something")


Would you do this instead?

foo = ['some', 'list', 'of', 'things']
spam(23, 42, ham=None, cheese="something", aardvark=foo)

on the basis that since aardvark will be ignored, it is perfectly safe to 
do so?

No, of course not, that would be stupid. Perhaps spam() has a bug that 
will mutate the list even though it shouldn't touch it. More importantly, 
you cause difficulty to the reader, who wonders why you are passing this 
unused and unnecessary aardvark argument to the function.

My argument is that this is equivalent to passing locals() as argument. 
Your local scope contains some arbitrary number of name bindings. Only 
some of them are actually used. Why pass all (say) 25 of them if the 
function only needs access to (say) three? To me, passing locals() as an 
argument in this fashion is a code-smell: not necessary wrong or bad, but 
a hint that something unusual and slightly worrying is going on, and you 
should take a close look at it because there *may* be a problem.


> So far, pretty much everyone who has tried to engage you on this subject
> on the list. I'm sorry we're not all ZOMGRUBYBLOCKS!!!!111 like the
> commenters on your project page.

Goddamit, did I miss a post somewhere? What the hell is this project 
people keep talking about?



-- 
Steven



More information about the Python-list mailing list