Johannes Bauer <dfnsonfsdu...@gmx.de> writes:

> I stumbled about something that I cannot quite explain while doing some
> stupid naming of variables in my code, in particular using "collections"
> as an identifier. However, what results is strange. I've created a
> minimal example. Consider this:
>
> import collections
>
> class Test(object):
>       def __init__(self):
>               z = {
>                       "y": collections.defaultdict(list),

This mention of collections refers to ...

>               }
>               for (_, collections) in z.items():

... this local variable.

>                       pass
>
> Test()

The same thing would happen in a plain function:

  import collections
 
  def f():
      z = { "y": collections.defaultdict(list) }
      for (_, collections) in z.items():
          pass
 
  f()

> In my opinion, this should run. However, this is what happens on Python
> 3.6.3 (default, Oct  3 2017, 21:45:48) [GCC 7.2.0] on linux):
>
> Traceback (most recent call last):
>   File "x.py", line 11, in <module>
>     Test()
>   File "x.py", line 6, in __init__
>     "y": collections.defaultdict(list),
> UnboundLocalError: local variable 'collections' referenced before assignment
>
> Interestingly, when I remove the class:

The significant change is removing the function that creates a local scope.

> import collections

This introduces "collections" as a global ...

> z = {
>       "y": collections.defaultdict(list),
> }
> for (_, collections) in z.items():

... and this uses that global ...

>       pass
>
> It works as expected (doesn't throw).

... except now collections is bound to a list (from the for) and no
longer refers to the module.

-- 
Ben.
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to