[Python-ideas] Tweaking closures and lexical scoping to include the function being defined
Devin Jeanpierre
jeanpierreda at gmail.com
Wed Sep 28 18:39:14 CEST 2011
> @init(n=1, lock=Lock())
> def global_counter():
> nonlocal n, lock
> with lock:
> print(n)
> n += 1
This use-case is no good. Consider:
_n = 1; _lock = Lock()
def global_counter():
global _n
with _lock:
print(n)
n += 1
Devin
On Wed, Sep 28, 2011 at 11:38 AM, Guido van Rossum <guido at python.org> wrote:
> On Wed, Sep 28, 2011 at 3:45 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:
>> Actually, there are some additional aspects that annoy me:
>> - the repetition of the variable name 'n'
>> - the scope of the variable name is wrong (since we only need it in
>> the inner function)
>> - indentation matters (cf try/except/finally)
>> - hidden signature for the actual function
>> - hoops to jump through to get decent introspection values (e.g. __name__)
>>
>> I find the following 5 line toy example:
>>
>> from threading import Lock
>>
>> def global_counter() [n=1, lock=Lock()]:
>> with lock:
>> print(n)
>> n += 1
>
> Hm, this syntax is *too* concise. It's lack of keywords makes it open
> to misinterpretation.
>
>> Far more readable than the 10-line closure equivalent:
>>
>> from threading import Lock
>>
>> @apply # I sometimes wonder if we should bring this back in functools...
>> def global_counter():
>> n = 1
>> local = Lock()
>> def global_counter():
>> with lock:
>> print(n)
>> n += 1
>> return global_counter
>
> True, the outer function completely obscures what's going on.
>
>> Or the 10-line 7-self class equivalent:
>>
>> from threading import Lock
>>
>> @apply
>> class global_counter:
>> def __init__(self):
>> self.n = 1
>> self.lock = Lock()
>>
>> def __call__(self):
>> with self.lock:
>> print(self.n)
>> self.n += 1
>
> Yeah, anything involving __call__ is hard to figure out.
>
> So after reading some previous messages, I almost wish we could
> implement the "decorator + nonlocal statement" proposal:
>
> @init(n=1, lock=Lock())
> def global_counter():
> nonlocal n, lock
> with lock:
> print(n)
> n += 1
>
> Alas, the problem is that you can't actually implement such a
> decorator, not even using an extension module, because the compiler,
> upon seeing the "nonlocal n, lock", ignoring the decorator (since it
> should be applied at run time, not at compile time), will complain
> that there isn't actually an intermediary outer scope defining either
> n or lock.
>
> Some ways out of this:
>
> - let the compiler special-case a certain built-in decorator name at
> compile-time (unorthodox, not impossible)
>
> - different syntax, e.g.
> @[n=1, lock=Lock()]
> or
> @in(n=1, lock=Lock())
> or even
> in n=1, lock=Lock()
>
> (all followed by "def global_counter() etc.")
>
> Of course once there's different syntax, the nonlocal declaration in
> the function is redundant. And clearly I'm back-peddling. :-)
>
> --
> --Guido van Rossum (python.org/~guido)
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> http://mail.python.org/mailman/listinfo/python-ideas
>
More information about the Python-ideas
mailing list