1

This code

def reportRealDiagnostics():

        ranks = 0
        class Rank: 
            def __init__(self):
                global ranks
                ranks += 1
        rank = Rank()

reportRealDiagnostics()

produces

NameError: global name 'ranks' is not defined

I am sure that this is all what you need to answer the question.

1
  • "I am sure that this is all what you need to answer the question." It would have been better to ask a question, starting with a question word like "why" or "how", and ending with a question mark (?). Commented Sep 11, 2022 at 9:40

2 Answers 2

3

When you use global ranks it looks for ranks in the global scope not in enclosing scope, so you get that error. The ranks you've defined is part of the enclosing scope.

In Python3 this has been resolved and you can modify ranks by using the nonlocal keyword:

def reportRealDiagnostics():
        ranks = 0
        class Rank: 
            def __init__(self):
                nonlocal ranks
                ranks += 1
        rank = Rank()

reportRealDiagnostics()

In Python2 you can define it as a function attribute:

def reportRealDiagnostics():
        class Rank: 
            def __init__(self):
                reportRealDiagnostics.ranks += 1
        rank = Rank()
reportRealDiagnostics.ranks = 0
reportRealDiagnostics()

There are some other alternatives too: nonlocal keyword in Python 2.x

Sign up to request clarification or add additional context in comments.

6 Comments

It is important to remember that the second option is not semantically the same. It puts ranks in the global scope, it is just hidden in the function's namespace. Multiple invocations of reportRealDiagnostics will use the same variable. It still might be OK.
There is a more serious problem than just global scope with python 2.x. The problem is that you must initialize the function-local variables every time before you call the function. This defeats the whole idea of having local variables.
@Val If you're talking about this, then this is not a issue related to py2.x, it works similarly in py3.x as as well. I wouldn't call it a issue as well.
Wait, you say that option is intended for Python2. Who cares about it regarding Py3?
My point was that you better declare a global variable as per normal rather than do it and initialize it properly at every call of you function. The point (of the very function) is that you initialize the ranks variable to a proper value in the parent function. Caller should not do that. He better not beware that such variable even exists. I have checked that you can declare the variable easily by simply defined in global reportRealDiagnostics function. You should have def f(): global r; r = 1; class C: __init__ global r; access(r)
|
0

You should use variable as nonlocal:

nonlocal ranks

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.