 I mentioned briefly before that local variables in a function of Python get created implicitly by assignments. Recall, though, how things work in JavaScript. In this JavaScript function, x here is a local variable because the function foo has a parameter named x, but the variable y here is not local because the function foo has no parameter named y. To make it a local variable, we have to explicitly declare that this function foo has a local variable y, with a var statement. In the Python version of this function, again, x is clearly a local variable because there is a local parameter x, but y is also a local variable just by virtue of the fact that we assigned to y in this function. That raises the question then, what if in the function you want to assign to a variable which is not part of the function? Well then, we have to do the inverse of what we do in JavaScript. In Python, we have to explicitly declare that a variable is not local to the function. And one way to do that is with the global statement. Here, the statement global y is declaring that in this function, y refers to a global variable. Global here meaning really a variable of the module. So now, the assignment of three to y is assigning three to y of the module, not a local variable y. There is no local variable y in this function. Now, it be clear that in cases where you just need to use a non-local variable, you don't need to declare that variable as non-local. You can just use it. And as long as you don't assign to a variable of that name in that function, Python understands that it's not local. So here in this function, if you write y assigned to x, well x of course is local, but y isn't as long as there's no y being assigned to in this function. Again, recall how JavaScript treats variables in nested functions. Here in the function bar, the interior function, when we assign it to y, the function bar doesn't have its own local variable y. So this must be something from the enclosing scope. In this case, it's y of the immediately enclosing function. If we want y in bar to be a local y, we have to declare it as such with a var statement. In Python in contrast, when we don't explicitly declare that y is non-local, it's assumed to be local just by virtue of the fact that we are assigning to it. If you want y in the function bar to actually refer to y of function foo, you have to declare it as such with a non-local statement. The non-local statement tells Python that this variable belongs not to this immediate function, but to some enclosing function. If instead of declaring y as non-local, we declared it global, that would mean that y in the function bar refers to y of the module, not y of the enclosing function. So to sum up the rules, if a name is assigned to y in a function, it is then a local of that function unless it is declared to be global in that function or non-local in that function. The difference between the two being that global makes it a variable from the module, while non-local means it must be a variable from some enclosing function. Now a subtle but important rule to keep in mind is that when you declare something non-local, there must actually be a variable of that name in an enclosing function. If there is no such variable, Python considers that an error and will throw an exception. Understand though this is only the case with non-local. If you declare in a function a global variable which doesn't actually exist in the module, that's perfectly fine because when in the function you actually do assign to that name, it will create the module variable of that name if it does not yet exist. That's a reasonable thing to do with modules because names assigned in modules are really just attributes added to the module object. It doesn't make any sense to do the same thing with non-local variables because how would you add a new local variable to some enclosing function? It just doesn't make any sense. So that's why Python has the double standard. When you declare a variable to be non-local, Python requires that such variable actually exist in an enclosing function. The body of a class in Python is considered its own scope but classes aren't really like functions. The variables we declare in classes become attributes of the class object. They're not really local variables. And moreover, classes have no concept of closure. So it's really a quite different thing going on in classes than compared to functions even though they are both scopes. And it is possible, of course, for a class to be nested inside a function or to be nested inside another class or to have other classes and functions nested within it. But the odd thing with classes is that any scope nested within a class cannot see the scope of the class itself. So here, for example, in this class, Steven, we are declaring a function foo and that function definition of foo is itself its own subscope of the class Steven. Inside that function, we can't directly refer to anything in the scope of the enclosing class. So here in the function when we return mark, presumably meant to refer to mark assigned in the Steven class, this actually doesn't work because mark of the Steven class is not visible. So the way around this is in the function we can refer to mark indirectly via the reference to the class object itself, because the class object is assigned to Steven in some enclosing class, which the function can see. So Steven dot mark will work that assumes, however, that Steven itself is not created directly inside another class, which would be an odd thing to do, but it is legal. So here when Steven is being created inside Kelly, so Steven becomes the only attribute of the Kelly class, inside that function foo to refer to mark, we now have to write Kelly dot Steven dot mark. Here we have to assume Kelly itself is not declared directly inside some other class. We have to assume it's a part of the module or created in some function. Because again, the rule is that inside a scope, you cannot see the scope of any enclosing class. Because a class is a kind of scope where assignments to names implicitly become parts of that scope. This means we have to use the non local and global statements if we want to assign to a name in that class body and have that name refer to something from an enclosing scope or the module scope rather than refer to an attribute of the class. Isn't truth would really be an odd thing to do, but I mentioned it really just for completeness and to drive home really how the scope of a class body works.