Variables in global python 3

2

In a cash register program, I have defined the variable "price" as global in a function. In another function I read it and it works well, but at the time of modifying it, it tells me that the variable is referenced before the assignment. How do I solve it, some other function? Error example: Compare Print in "Finticket ()" and "Return ()"

print ("**********MAQUINA REGISTRADORA***********")
import time
inventario = [["leche", 1.50, 300], ["lista", 2.35, 400], ["pan", 0.50, 200]]
lista = []



def añprod(prod, prec, cant):#-----------------------funciona
    np = [prod, prec, cant]
    inventario.append(np)
    print ("""Producto Añadido:
    Producto = {}

    Precio = {}
    Cantidad = {}""".format(prod, prec, cant))
    print ("")
    inventario


def ticket(prod, cant):#-----------------------------funciona

    global posprod
    global canttick
    global  precio#--------+++++aquí defino precio+++++---------  
    precio = 0
    i = 0

    canttick = cant
    numprod = len(inventario)

    for a in inventario:
        if prod in a:
            posprod = inventario.index(a)#comprueba si existe el producto

            if cant <= 0:#comprueba si la cantidad es negativa
                print ("Si desea devolver un producto, use la función 'devolver([producto])'")
                break

            if inventario[posprod][2] >= cant:#comprueba el stock
                inventario[posprod][2] -= cant#quita lo pedido del inventario
                print ("En ticket")
                pyc = [prod, cant]

                for a in lista:#comprueba si el producto está repetido 
                    if prod in a:
                        prodrep = lista.index(a)
                        lista[prodrep][1] += cant
                        break
                else:        
                    lista.append(pyc)#añade el producto al ticket

                precio += precio + inventario[posprod][1] * canttick
                break
            else:
                print ("No en Stock")

        else:
            i = i+1

    if i == numprod:
        print ("Producto no encontrado")


def finticket():#------------------------------------funciona

    print ("Productos en lista:")   
    print (lista)
    print ("")
    print ("Precio final: {} €".format (precio))#-------+++++aquí uso precio y funciona++++++++-------------

def devolver(prodev, cantdev):
    print ("Precio: {}".format (precio))#-----++++aquí uso precio y falla+++++-------
    i = 0 
    nprod = len(lista)
    for a in lista:#Comprueba si el producto existe
        if prodev in a:

            if cantdev <= 0:#Comprueba si la cantidad es válida
                print ("Cantidad inválida")
                break

            else:#resta la cantidad indicada
                for prod in inventario:
                    if prodev in prod:
                        if cantdev > a[1]:#comprueba y devuelve el producto 
                            cantinv = cantdev - a[1]
                            op = cantdev - cantinv
                            prod[2] += op

                            precio -= (prod[1] * op)#devuelve el dinero------++++da error++++------

                            print ("Producto devuelto")

                        else:
                            prod[2] += cantdev#devuelve el producto

                            precio -= (prod[1] * cantdev)#devuelve el dinero ----++++da error++++----

                            print("Producto devuelto")

                a[1] -= cantdev

                if a[1] <= 0: #Comprueba y elimina el producto si < 0
                    posdev = lista.index(a)
                    del lista[posdev]
                    break

        else: 
            i += 1

    if i == nprod:
        print ("Producto no encontrado")
    
asked by Esteban 30.03.2018 в 20:32
source

1 answer

1

This is a problem that sooner or later ends up happening to all of us ...

When a function refers to a variable to read it , this variable is searched first among the premises of the function, and if it does not appear there, then it is searched among the global ones (even if it is not has declared as global within the function).

However, if a function refers to a variable to assign it , then, unless declared global within the function, a local variable will be created, even if there is a global variable same name.

For example:

v_global = 10

def lee_v_global():
    print(v_global)

def escribe_v_global_y_no_funciona():
    v_global = 20    # Crea en realidad una local
    print(v_global)

print(v_global) # Saldrá 10
lee_v_global()  # Saldrá 10
escribe_v_global_y_no_funciona()  # Saldrá 20
print(v_global) # Sigue siendo 10

To work properly it should be:

def escribe_v_global_bien():
    global v_global    # Declaramos explícitamente la variable
    v_global = 20      # Ahora sí, asignamos la global

And now entering the concrete problem that appears to you, what do you think the following code would do?

def funcion_sorpresa():
    # No declaro la variable como global
    print(v_global)   # ¿Escribiría 10?
    v_global = 20     # Y ahora? Está cambiando la global o la local?

Well, what happens is that before you execute the python functions, you "compile" them (to make sure they do not have syntactic errors and to convert them to a faster bytecode to interpret). And during that phase you see the assignment of the last line, and therefore you will consider the variable as local, and in the bytecodes that you generate, you will refer to that local variable. When you start to execute it, the first line that the variable tries to print (which the bytecode treats as local) finds that that variable still has no value, and that's where the infamous one comes from:

UnboundLocalError: local variable 'v_global' referenced before assignment

The solution is obviously to declare that variable as global within that function:

def funcion_sin_sorpresa():
    global v_global
    print(v_global)   # Escribirá 10
    v_global = 20     # Y modifica la global

Moraleja Always declare as global the global variables that you are going to use in the functions, even if it is not necessary (in case you only read them and do not modify them). It never hurts and in fact the program will be more readable.

    
answered by 30.03.2018 / 21:01
source