1

Here's my test script:

def main(): #global
    n = 1
    z = None

    def addone():  #local
        if not z:
            n = n+1
    addone()
    print n

main()

I step into the addone() function once it hits the calling line. At this point I can only see the variable z, but cannot see n.

Now, if n is referenced before assignment, shouldn't z be too?

Similarly, if I change n=n+1 to z='hi', I can no longer see z! This is contrary to all my previous beliefs about local/global functions! The more you know, the more you know you don't know about Python.

Question(s):

  • Why can I see one but not the other?

  • Do I want to be prepending global to these variables I want to reassign?

martineau
  • 119,623
  • 25
  • 170
  • 301
tenwest
  • 2,058
  • 1
  • 13
  • 16
  • Perhaps this might be helpful: http://stackoverflow.com/a/21978980/748858 – mgilson Jan 15 '15 at 02:47
  • ah ha, useful indeed. thanks. I would have thought I had to use `global` outside of the function, but nice that i can use it within. – tenwest Jan 15 '15 at 03:06
  • wait...maybe it is as I thought. doesn't `global` have to be defined **outside** of the function? I am getting a `NameError: global name 'x' is not defined`. calling it `global` outside of the function as well causes it to work. – tenwest Jan 15 '15 at 03:13

2 Answers2

1

The best solution is to upgrade to Python 3 and use in the inner function nonlocal n. The second-best, if you absolutely have to stick with Python 2:

def main(): #global
    n = [1]
    z = None

    def addone():  #local
        if not z:
            n[0] += 1
    addone()
    print n[0]

main()

As usual, "there is no problem in computer science that cannot be solved with an extra level of indirection". By making n a list (and always using and assigning n[0]) you are in a sense introducing exactly that life-saving "extra level of indirection".

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • Unfortunately I am constrained to python2...this is a very interesting workaround, I may use it for now as I don't think we want to be declaring the variable in question as a `global`. – tenwest Jan 15 '15 at 03:14
  • @tenwest, yep, `global` should be avoided whenever possible! – Alex Martelli Jan 15 '15 at 03:15
0

Okay, after some testing, I realised that it all has to do with the reassignment of variables.

for example:

def main(): #global
    n = 1
    z = None

    def addone():  #local
        if not z:
            x = n+1
    addone()
    print n

main()

Now shows both n and z when I am inside the addone() function. This is because I am no longer trying to reassign n, makes sense to me so as to protect global variables from manipulation if one so happens to use similar names in local functions.

mgilson
  • 300,191
  • 65
  • 633
  • 696
tenwest
  • 2,058
  • 1
  • 13
  • 16