[Python-ideas] Before and after the colon in funciton defs.
Sven Marnach
sven at marnach.net
Mon Sep 19 15:22:18 CEST 2011
Nick Coghlan wrote:
> [...] allow a sequence of 'implicit locals' to be defined within
> square brackets after the parameter list.
I'm not quite sure whether the benefits of this proposal are worth the
further rococoization of the language. As far as I can see, the only
benefit is keeping function signatures clean.
Looking at the use cases one by one:
> Micro-optimisation:
> # Current Python (internal to functools.lru_cache with default
> argument hack)
> def decorating_function(user_function, tuple=tuple, sorted=sorted,
> len=len, KeyError=KeyError):
> ... # 60 line function
>
> # Proposal - explicitly implicit locals to clarify real calling signature
> def decorating_function(user_function) [tuple=tuple,
> sorted=sorted, len=len, KeyError=KeyError)]:
> ... # 60 line function
The proposed syntax isn't explicit enough for my taste to justify the
change. What the programmer really wants to tell the compiler is:
Bind the given names at compile time rather than at run time. I'd
prefer if the syntax would reflect this intention, similar to the
"global" and "nonlocal" declarations:
def decorating_function(user_function):
earlybind tuple, sorted, len, KeyError
(Not being a native speaker of English, I don't even try to find a
less dull name for this than "earlybind". And I'm quite aware that
the bar for the introduction of a new keyword is quite high.)
> Early binding in a loop:
>
> # Current Python
> adders = []
> for i in range(10):
> def f(x, _i=i):
> return x + _i
> adders.append(f)
>
> # Proposal
> adders = []
> for i in range(10):
> def f(x) [i=i]: # Real calling signature is clear
> return x + i
> adders.append(f)
I don't see too much benefit of the proposed syntax for this use
case. If f() is a local throw-away function, I wouldn't worry about
its signature. If f() is a longer-lived object and I do care about
its signature, I'd uses a class:
class Adder:
def __init__(self, i):
self.i = i
def __call__(self, x):
return x + self.i
[...] adders.append(Adder(i))
I still think classes are the Python way to hide state, not closures.
That said, this case would also be covered by the "earlybind" porposal
above.
> Algorithmic shared state (without a class):
>
> # Current Python
> def f(*, _cache=[]):
> # Consenting adults, please don't override _cache when calling!
>
> # Proposal
> def f() [_cache=[]]: # Real calling signature is clear
> # _cache is an implicit local, not a keyword-only argument, so its safe
Again, I'd use a class to hide state in the first place. If someone
really wants to avoid using a class for some reason, using function
attributes would also be a viable way:
def f():
try:
cache = f._cache
except AttributeError:
cache = f._cache = []
Cheers,
Sven
More information about the Python-ideas
mailing list