[Python-ideas] PEP 572 version 2: Statement-Local Name Bindings

Nick Coghlan ncoghlan at gmail.com
Sat Mar 24 23:13:59 EDT 2018


On 25 March 2018 at 01:03, Kirill Balunov <kirillbalunov at gmail.com> wrote:

>
>
> 2018-03-24 17:14 GMT+03:00 Nick Coghlan <ncoghlan at gmail.com>:
>>
>>
>> They can be distinguished, just not at module or function scope. To give
>> a concrete example:
>>
>> ==========
>>     >>> class C:
>>     ...     sequence = range(10)
>>     ...     listcomp = [x for x in sequence]
>>     ...     def works(data):
>>     ...         return list(data)
>>     ...     from_works = works(sequence)
>>     ...     def fails():
>>     ...         return list(sequence)
>>     ...
>>     >>> C.listcomp
>>     [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>     >>> C.from_works
>>     [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>     >>> C.fails()
>>     Traceback (most recent call last):
>>       File "<stdin>", line 1, in <module>
>>       File "<stdin>", line 8, in fails
>>     NameError: name 'sequence' is not defined
>> ==========
>>
>> I think I did have an implementation that didn't do the "outermost
>> iterator is evaluated in the outer scope" dance early on (back when I was
>> still working on the initial version of the iteration variable hiding,
>> before it was merged to the Py3k branch), but quickly changed it because
>> relying solely on closures broke too much code (in addition to the class
>> namespace case, you can create a situation with similar constraints by
>> passing a separate locals namespace to exec).
>>
>> Cheers,
>> Nick.
>>
>
> But is the example with the class appropriate in this context, it seems
> that it is well understood why this example will fail, and  `C.fails()`
> should at least be a `@classmethod`:) From the docs:
>
>> Class definition blocks and arguments to exec()
>> <https://docs.python.org/3/library/functions.html#exec> and eval()
>> <https://docs.python.org/3/library/functions.html#eval> are special in
>> the context of name resolution. A class definition is an executable
>> statement that may use and define names. These references follow the normal
>> rules for name resolution with an exception that unbound local variables
>> are looked up in the global namespace. The namespace of the class
>> definition becomes the attribute dictionary of the class. The scope of
>> names defined in a class block is limited to the class block; it does not
>> extend to the code blocks of methods – this includes comprehensions and
>> generator expressions since they are implemented using a function scope.
>
> And if we cross out class, exec and eval cases - they don't work now, they
> will not be affected in future. Are not these examples equivalent?
>

I don't follow what you're trying to say here. Comprehensions *do* work
with class bodies, two-namespace exec, and two-namespace eval, and one of
the consequences of the *way* they work that proposals for expression level
name binding will all have to deal with is that the outermost iterable
expression is evaluated in the containing scope rather than the implicitly
nested one.

Statement local name bindings would restrict any resulting name leakage
from the outermost iterable to the affected statement, while regular name
bindings would affect the entirety of the containing scope.

The latter behavour is of the larger downsides of having expression level
name bindings work the same way assignment statements do, since it
recreates a variant of the original iterator variable name leakage that the
introduction of the implicitly nested scope eliminated.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180325/cad7e937/attachment.html>


More information about the Python-ideas mailing list