3

This:

import os

class A(object):

    os_sep = os.sep
    _silentSkipsStart = {u'a dir%s' % os_sep}

    def _refreshBasic(self,os_sep=os_sep, skips_start=tuple(
                x.replace(os_sep, u'') for x in _silentSkipsStart)):
        pass

Fails with:

Traceback (most recent call last):
  File "C:/Users/MrD/.PyCharm50/config/scratches/scratch", line 3, in <module>
    class A(object):
  File "C:/Users/MrD/.PyCharm50/config/scratches/scratch", line 9, in A
    x.replace(os_sep, u'') for x in _silentSkipsStart)):
  File "C:/Users/MrD/.PyCharm50/config/scratches/scratch", line 9, in <genexpr>
    x.replace(os_sep, u'') for x in _silentSkipsStart)):
NameError: global name 'os_sep' is not defined

I guess that bringing os_sep = os.sep to global scope should cure that (and I probably should from a design point of view) - but here I am not getting python scoping rules: why is os_sep resolved alright in the other cases and not in genexpr ?

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
  • 1
    http://stackoverflow.com/questions/30444962/python-beginner-class-variable-error/30445493#30445493 if you used a list comp it would work in python2 – Padraic Cunningham Mar 23 '16 at 17:02
  • @PadraicCunningham: "if you used a list comp it would work in python2" - thanks! Should I delete this ? – Mr_and_Mrs_D Mar 23 '16 at 17:08
  • @Mr_andMrs_D, no worries, it is up to yourself, if you fancy writing an answer with what worked fire ahead. – Padraic Cunningham Mar 23 '16 at 17:25
  • Well it's an exact duplicate - for the record I did use a comprehension - now a shame that the IDE (Pycharm) does not notify but resolves os_sep just fine in the genexpr – Mr_and_Mrs_D Mar 23 '16 at 17:28
  • 1
    It happens, if you had something like `foo = ["foobar"]` declared after the class and used for in your loop pycharm would also not warn you even though you would get the same error, the scoping rules are obviously slightly different for pycharm. – Padraic Cunningham Mar 23 '16 at 17:39
  • 1
    Note that if you do use a list comprehension in Python 2, the loop variable `x` will leak out into the class namespace. – Blckknght Mar 23 '16 at 17:49
  • Thanks @ both - Blckknght, well that too escaped me although I should have seen that (there is an example precisely for that in the answer linked by Padraic) Turns out there are a lot of subtleties involved - hmmm I tend now towards the "real global variable" solution - judging by the IDE missing this it would be probably missed by 2to6 tools too (dunno). Plus leaking in class scope - eeek ! – Mr_and_Mrs_D Mar 23 '16 at 18:32

1 Answers1

1

Well as explained to the answer linked in the comments by @PadraicCunningham:

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

That is for python 3 - for python 2 list comprehensions would work - but the comprehension variable would leak into class scope - so this would leak x:

    def _refreshBasic(self,os_sep=os_sep, skips_start=tuple(
                [x.replace(os_sep, u'') for x in _silentSkipsStart])):
        pass

So I went with:

import os

os_sep = os.sep
class A(object):
    _silentSkipsStart = {u'a dir%s' % os_sep}

    def _refreshBasic(self,os_sep=os_sep, skips_start=tuple(
                x.replace(os_sep, u'') for x in _silentSkipsStart)):
        pass
Community
  • 1
  • 1
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361