Create global variables in Python

I'm pretty new to Python syntax in particular How to create global, nonlocal and local variables and how to declare them without syntax errors.

For example in the following program, I have

# Estamos creando el juego de Piedra, papel o tijera

import random

userScore = 0;
cpuScore = 0;
global noChoice = True;



# result viene de que los jugadores han elegido, no muestro esta parte
# porque no es necesario por el tema de errores de sintaxis por las variables
def result(userChoice, cpuChoice):



# Traimos de saber lo que el usuario quiere elegir como estrategia
def start():
    while (noChoice):
        try:
            userChoice = int(raw_input("Make a move: Rock = 1, Paper = 2, Scissors = 3"));
        except ValueError: "That's definitely not a number"
        if userChoice == {1,2,3}:
            global noChoice = False;
            print "Oops!  That was no valid number.  Try again..."

    cpuChoice = random.getInt();

start()

This gives the following result:

:~$ python pFC.py
  File "pFC.py", line 7
    global noChoice = True;
                    ^
SyntaxError: invalid syntax

I have used global but it says I have declared the variable too soon.

UnboundLocalError: local variable 'noChoice' referenced before assignment

I have used what I have been advised, but the error remains

# Estamos creando el juego de Piedra, papel o tijera

import random

user_score = 0
cpu_score = 0
global no_choice = True



# result viene de que los jugadores han elegido, no muestro esta parte
# porque no es necesario por el tema de errores de sintaxis por las variables
def result(user_choice, cpu_choice):


# Traimos de saber lo que el usuario quiere elegir como estrategia
def start():
    #Hey Python! Vamos a utilizar una variable global!
    global no_choice
    while (no_choice):
        try:
            user_choice = int(raw_input("Make a move: Rock = 1, Paper = 2, Scissors = 3"))
        except ValueError: "That's definitely not a number"
        if user_choice == {1,2,3}:
            global no_choice = False
            print "Oops!  That was no valid number.  Try again..."

    cpuChoice = random.getInt();

start()
 7
Author: Shassain, 2016-05-23

4 answers

Well, I think I'll start by recommending you take a look at PEP 8 Style Style Guide for Python Code which is the style guide you should keep in mind when using Python.

For example, for the definition of variables CamelCase is not used nor is it necessary to use ; at the end of each statement:

userScore = 0;
cpuScore = 0;

Should be converted to:

user_score = 0
cpu_score = 0

Note that PEP 8 is just a guide, if you prefer to follow doing it your way, it's fine.


Now yes, regarding global variables in your code. The problem is that you are doing it the wrong way.

Consider this script that we will be creating progressively:

# -*- coding: utf-8 -*-

# Es una variable global disponible para cualquier función definida dentro de
# este script
no_choice = True

def start():
    # No es necesario indicar que quieres usar la variable global
    print "El valor de no_choice es:", no_choice

if __name__ == '__main__':
    start()

The result would be:

El valor de no_choice es: True

Notes that I am not using global since using global it's not to define a global variable (even if you're tempted to do it by name).

Now, imagine you want to modify the variable no_choice:

# -*- coding: utf-8 -*-

# Es una variable global disponible para cualquier función definida dentro de
# este script
no_choice = True

def start():
    # No es necesario indicar que quieres usar la variable global
    print "El valor de no_choice es:", no_choice
    # Quiero negar el valor de no_choice (cambiarla a False)
    no_choice = not no_choice

if __name__ == '__main__':
    start()

This will generate an error:

El valor de no_choice es:
Traceback (most recent call last):
  File "test.py", line 14, in <module>
    start()
  File "test.py", line 9, in start
    print "El valor de no_choice es:", no_choice
UnboundLocalError: local variable 'no_choice' referenced before assignment

Python doesn't know which variable no_choice you mean and assumes it must be one within the scope of the function start, but it doesn't find it and throws the error UnboundLocalError (which happens when you're trying to use a variable that hasn't been defined).

Now, in order to modify it, we have to tell Python that we want to use the variable global, in this case we do have to use global:

# -*- coding: utf-8 -*-

# Es una variable global disponible para cualquier función definida dentro de
# este script
no_choice = True

def start():
    # Hey Python, voy a usar una variable global
    global no_choice
    print "El valor de no_choice es:", no_choice
    # Quiero negar el valor de no_choice (cambiarla a False)
    no_choice = not no_choice
    print "Ahora el valor de no_choice es:", no_choice

if __name__ == '__main__':
    start()

The result would be:

El valor de no_choice es: True
Ahora el valor de no_choice es: False
 10
Author: César, 2016-05-23 20:32:33

You don't need the word global when you declare it, because being outside the definition of a function it automatically becomes global, but if you need the identifier global in the functions that are going to modify it, but declaring it first like this:

  if userChoice == {1,2,3}:
        global noChoice
        noChoice = False;
        print "Oops!  That was no valid number.  Try again..."
 7
Author: Eduardo Hernández, 2016-05-23 20:30:59

Well, as for the recommendations and good practices, you've already seen it in other answers.

To answer your question, I will mention the errors that I have noticed from the beginning First:

no_choice = True

When declaring a variable you don't need to use global, You just declare it by its name, its situation as global or local, is implicit(global in that case).

Then, by using" global no_choice " inside the def start() you create a reference to the variable outside the def (osea in the global scope), that in my opinion is "legal"

About the "if user_choice == {1,2,3}". The latter will possibly give you an error if you use it that way, since what the user entered will only be one of those numbers, not a list with all of them. I recommend changing it to:

if user_choice in {1,2,3}

As for the "global no_choice=False", you'd better leave it as:

no_choice=False

With the "global" you put at the beginning of def start (), you already let python know which you wanted to modify, no need to use it again.

Finally, the cpuChoice variable, if you are going to use it outside the def then, I would recommend declaring it with the others But if you want to declare a global variable from within the some def:

>>>globals().update({"nombre_de_variable":3}) #el 3 es el valor de ejemplo, puedes usar un string u otra variable
>>>nombre_de_variable
3

This declares the variable accessible from any (global) site

On the random, the def to select a random number is randint (minimum,maximum), so I imagine you will use:

globals().update({"cpuChoice":random.randint(1,3)})

Or if not you plan to create the global variable

cpuChoice=random.randint(1,3)

Summary:

To use the information of a global variable you do not need to use "global", just to edit it, and if you are going to edit it first

global variable
variable="nuevo valor" # no puedes hacer ambas en una sola linea

Or the other option that also declares the variable in case it does not exist.

globals().update({"variable":"nuevo valor"})

To create and modify local variables you do not need to use any special words. And in case of nonlocal, you only use them when you put one def inside another, I do not recommend it, but if you want an example https://www.smallsurething.com/a-quick-guide-to-nonlocal-in-python-3 /

Greetings and good luck n_n

 3
Author: Julio González, 2017-04-17 00:24:42

By completing the previous answers, which have focused rather on fixing your code, I am going to give a slightly more generic answer that defines what each type of variable is and in particular explains the nonlocal by which you were asking that has not been dealt with in the answers.

Local

There is no such reserved word in Python. You can't "declare" a variable as local. is automatically considered local any variable that is assigned within of a function .

For example

def test():
    x = 1
    print(x)

Due to the fact that the assignment x=1 appears inside the function, (not necessarily in the first line, but anywhere in the function), the variable x is already considered local.

Naturally the assignment must occur before trying to use it because if you try the other way around:

def test_mal():
    print(x)
    x = 1

When I try to do print(x) the variable still has no value, and it will give you the error " local variable 'x' referenced before assignment "

Global

A global variable is one that is assigned outside functions. Being global is "visible" by any function that can use its value. Example:

x = 0  # Es global por estar fuera de las funciones
def test():
    print(x)

But there is a potential conflict. If a function tries to change the value of x, with something like this:

x = 0
def test_mal():
    x = 1
    print(x)

So because a assignment appears inside the function and according to what is explained in the above, the variable x will be considered local. Therefore, a new function-specific variable x is created that will prevent access to the global variable of the same name. Although print(x) will show 1, that is a local value. When the function finishes, it will cease to exist. The global x will still be worth zero.

Because this x is local, we can pose the exact same problem already seen if we modify it inside the function, but the we tried to use before had modified it, like this:

x = 0
def test_mal():
    print(x)
    x = 1

Because before you even try to run this function python has already seen that in some line of it a value is assigned to x, it will consider x local. Therefore the first print(x) will try to print the local variable and since it does not yet have a value assigned, the error will occur.

To solve this problem there is the word global that allows you to specify Python that even though you see an assignment inside the function, you don't create a new local variable, but make use of the global one. Like this:

x = 0
def test():
    global x
    print(x)
    x = 1

In this case, the references that occur to x within the function test() access the global x, so not only does the code fail, but when the function finishes executing the value of the global x will have changed.

Nonlocal

This word exists for a very particular case, and is that of functions nested that need to access variables that are neither local to the nested function itself, nor global, but are variables of the function within which they are nested.

If the above looks like a tongue twister, let's try to see an example:

x = 0
def test():
    x = 1

    def anidada():
        x = 2
        print(x)

    anidada()

What will this program print if I run test()? How much will the global variable x be worth when terminated?

When executing test(), since it contains an assignment x=1 and has not said to use the x global, a new local variable is created for the function test(). We could call it "test.x" (although this syntax is not correct, it helps to see that it is an X that" belongs " to test). That is given the value 1 (the global x is still worth 0)

Then a nested function is defined, and the nested function is invoked. Inside it there is an assignment x=2, but since the x has not been said to be global, a local will be created again. To understand us let's call it "test.nest.x", and it is assigned the value 2. The global is still worth 0.

So a 2 will be printed and the global one will still be worth 0.

If we wanted the function anidada() to modify the value of the global, the solution is simple and we already know it:

x = 0
def test():
    x = 1

    def anidada():
        global x
        x = 2
        print(x)

    anidada()

In this example we continue to create the variable we had called " test.x", but a "test is no longer created.nest.x", but the x=2 acts on the global.

But what if we wanted from anidada() modify the local x from test()? That is, somehow I want x=2 to modify " test.x".

For this is the word nonlocal:

x = 0
def test():
    x = 1

    def anidada():
        nonlocal x
        x = 2
        print(x)

    anidada()

When Python sees nonlocal x it knows that even if that function tries to assign values to a x, it should not create a local variable for it. You must use the x that is accessible within your scope (which will be the one defined in the assignment x=1)

 3
Author: abulafia, 2019-07-19 06:51:56