-1

I have this dictionary and two functions.

marcador_game = {1: 0, 2: 0}

def punto_jugador(jugador):
    marcador_game[jugador] += 1 # here I can use the dictonary without problems

    if marcador_game[1] > marcador_game[2]:
        return (1, 2)
    else:
        return (2, 1)

def calcular_puntaje(j_mayor, j_menor):
    if marcador_game[j_mayor] > marcador_game[j_menor]: # here tell's me that variable is not declared
        if marcador_game[j_mayor] == 4 and marcador_game[j_menor] < 4:
            marcador_game = {1: 0, 2: 0}
            marcador_sets[j_mayor] += 1

I can only use the dict in the second function if I use the dict as global before the if:

global marcador_game

Why I can alter the dict in the fist function but not evaluate it in the second?

Kaz Miller
  • 949
  • 3
  • 22
  • 40
  • Because you _modify_ the dict in the first function, but in the second you reassign the name `marcador_game` to a completely new dictionary – Pranav Hosangadi Jan 21 '22 at 21:58
  • 1
    Duplicate of [this](https://stackoverflow.com/questions/65515527/unbound-local-error-within-multiple-functions) – MYousefi Jan 21 '22 at 22:04
  • You can *reference* a variable from any scope using the usual scoping rules, [local, enclosing, global, built-in]. But if you **assign** to a variable, that variable will automatically be marked as local by the compiler, unless you use a `global` or `nonlocal` statement – juanpa.arrivillaga Jan 21 '22 at 22:05
  • And very important to understand, `marcador_game = {1: 0, 2: 0}` **does not alter any dict** – juanpa.arrivillaga Jan 21 '22 at 22:13
  • @MYousefi that help me understand better the problem than the question referenced as already answered. Thnx – Kaz Miller Jan 21 '22 at 22:15
  • So is it better to put global in the send function or pass the dict as a parameter? – Kaz Miller Jan 21 '22 at 22:22
  • @KazMiller `global` is almost always an anti-pattern. And you should almost certainly just be using parameters and return values – juanpa.arrivillaga Jan 21 '22 at 22:22
  • @juanpa.arrivillaga in this case I can pass the dict as a parameter and reasign it inside the function, actually reasigning the original(global scope) dict, without return in the function. That is because I'm passing an object(in this case a dict) to the function, right? – Kaz Miller Jan 21 '22 at 22:39
  • @KazMiller no, you are describing call by reference, which does not exist in python. Just return the value you want to the caller, and it is up to the caller to decided how to handle it – juanpa.arrivillaga Jan 21 '22 at 23:24
  • @juanpa.arrivillaga that works for simple data types, as int and str. When you pass a list or a dict, the value passed as parameter in the function actually changes the original list or dict, even when you reasign the param value inside the function. If it is not reference, how is named in python? – Kaz Miller Jan 21 '22 at 23:43
  • @KazMiller no, that is **absolutely inccorect**. There is *no distinction* between "simple types" and other types in Python. *everything* is an object, and the evaluation strategy is the same regardless of type, it is **neither** call by reference nor call by value, but "call by sharing" if you want a rather arcane term. Reassignment to a paramter **is never seen in the caller**. Ever. This is easily verifiable. `def foo(x): x = []` then `data = [1,2,3]; foo(data); print(data)` will print `[1, 2, 3]` not `[]` – juanpa.arrivillaga Jan 22 '22 at 03:36

1 Answers1

0

In the second function, you are overwriting the global variable like marcador_game = {1: 0, 2: 0}, and try to read from the same variable earlier. That confuses python. It takes marcador_game as a local variable to you declarer in the namespace of the function. Hence, you have to tell python that this is the global variable using the global keyword. In the first you are just reading it, or changing values within it if you want to. Therefore, you don't need the global keyword.

Simon Hawe
  • 3,968
  • 6
  • 14