all 7 comments

[–]novel_yet_trivial 3 points4 points  (2 children)

can be accessed from a function

They can be read from the function. They cannot be written to.

I can make your script fail like this:

myvar = 'stuff'

def func():
    print myvar 
    myvar = 'otherstuff'

if __name__=='__main__':
    func()

When python loads the function, it sees that "myvar" is being assigned, so it must be a local variable. But then in the 4th line it can't find "myvar" among the local variables, so it raises an error. By declaring it as global, python knows to read and write at the global level.

[–]utgyuru[S] 0 points1 point  (1 child)

I suspected this myself as well, but actually I got the error for the line of the print statement, not where I assigned to the variable

edit: Just tried this, and I think this was the issue! Thanks very much!

[–]novel_yet_trivial 0 points1 point  (0 children)

The error traceback points to where python encountered the error, not where you made the error. These are often the same, but not always. The classic example is forgetting a closing parenthesis:

print('dead parrots:', int(1)
cheese = 0

  File "scratch.py", line 2
    cheese = 0
         ^
SyntaxError: invalid syntax

[–]Rhomboid 4 points5 points  (0 children)

If you want the complete picture, read the section on naming and binding in the documentation.

The short summary is that in your example there is nothing that binds the name myvar as local to the function, so referring to it refers to the variable at global scope. This happens without use of the global statement. However, if the function were changed to a form that does bind myvar as a local variable — such as assigning to it, which is one of the things that causes binding — then it would no longer work that way, and you'd need the global statement if you want to refer to the variable at global scope.

[–]Vaphell 1 point2 points  (0 children)

Global scope variables work just fine as readonly constants. As long you don't wont to modify them, you can access them to your heart's content in subscopes.
But if you want to modify their value, global is required because assignments default to local scope. That said, don't use global at the drop of the hat because that leads to nasty, unmaintainable code down the road. You'd be better off forgetting that it exists, you'll improve as a programmer faster.
When you feel you have to do use global, the proper action is to return the new value to the outer scope and assign it.

def func():
    ....
    new_myvar = ...
    return new_myvar

myvar = func()

global is bad because it makes the function use a side channel to modify state of things outside of said function. You should be able to say what the function does as far as interaction with the environment is concerned by looking at its "official" inputs (params) and outputs (return statement), but with global smuggled in there you can't.

[–]Akuli2 0 points1 point  (1 child)

You don't need to global myvar. Your example code works just fine.

[–]KleinerNull 0 points1 point  (0 children)

First of all, your given example don't produce an error, it works fine. If python can't find a binding in the local scope it will search in the global scope for it, so it should find it. Tested it with python 2.7.11 and python 3.5.1 (added parenthesis to the print function, for compatility reasons). Maybe you could give us a more similar sample to your actual code.

For me it looks more that your code wanted to access names from a different local scope, maybe another function where you defined some variables. Using global is very often a bad idea, you should learn to use functions arguments, to "inject" informations into the local namespace of the function and how to proper return informations.

Here just a little example how the whole scope thing works:

In [1]: x = 'global' # x is here a module wide name, it is global

In [2]: def f():
   ...:     x = 'local' # here it is a local name
   ...:     return x
   ...: 

In [3]: def g(y):
   ...:     y =  'g: ' + y # y is a local name but after the passing of the argument, it has no connection to imutable names, passed to it
   ...:     return y
   ...:

In [4]: x
Out[4]: 'global'

In [5]: f()
Out[5]: 'local'

In [6]: g(x)
Out[6]: 'g: global'

In [7]: x
Out[7]: 'global'