Consider the code below:
lancar = 'abc'
def faz_algo(lancar):
lancar = 1
faz_algo(lancar)
print(lancar) # aqui vai imprimir o que?
In his mind, he should print 1
. After all, I created the variable lancar
with the value 'abc'
, and passed it to the function faz_algo
. But within the function I set her value to 1
, then after the function performs, its value should be 1
, right?
Wrong. The above code prints "abc" (can check out).
To understand what happens, there are a number of concepts to be understood. I will give a more "simplistic" explanation and try to be didactic without sticking to too many technical terms, and not even go into Python implementation details (but I will put some links for you to delve into the subject). The idea is to understand in general what is happening.
First, just think that the variable lancar
created out of function nay is the same variable lancar
which has been declared as a function parameter. They happen to have the same name, but this is circumstantial, after all, you could call the function in other ways, without having to create the variable lancar
:
# sem usar variável
faz_algo('abc')
# usando variável com outro nome
x = 'abc'
faz_algo(x)
# usando uma outra função que retorna algum valor
faz_algo(outra_funcao()) # assumindo que outra_funcao() retorne alguma coisa
That is, the value that is passed to the function is copied to the parameter lancar
, and what happens inside does not interfere with the variable lancar
outside (if it exists, because in the above examples it does not exist, and this does not prevent the function to perform anyway).
I mean, when I do faz_algo(lancar)
, what happens is more or less the following:
- the value of the variable
lancar
(external, which was created outside the function) is passed to the function faz_algo
- this value is copied to the parameter
lancar
- even if within the function I assign another value to
lancar
, I am only changing his "internal version" (the one that exists inside the function), without interfering with the variable lancar
external
As I said, it is a simplified explanation and without clinging to the correct terminology for all things, nor to the internal details of language implementation.
Basically, that’s why you’re having this behavior in your code. Within the function you convert the parameter lancar
for int
, but the external variable remains string
(it is not affected by what happens within the function, since it is not the same variable - they only have the same name, but one exists only within the function and the other exists only outside).
Every rule has exceptions
Of course you can access the external variable (which in this case we call "global") within the function, as already explained another answer. Of course, there are cases where it is possible to change the data within the function, just by changing the type (like a list, for example):
def muda_lista(lista):
lista.append(3)
x = [1, 2]
muda_lista(x)
print(x) # [1, 2, 3]
But it doesn’t work the same way if we assign another value to the list:
def muda_lista(lista):
lista = [1, 2, 3]
x = [1, 2]
muda_lista(x)
print(x) # [1, 2]
Good, but maybe I’m already confusing more than helping. Leave this example of the lists aside and let’s get back to your case.
There are two concepts you should understand: passing by value and passing by reference. So well summarized, when you pass parameters to a function, you can pass only the values, and the function receives a copy of them, and whatever it does inside does not interfere with the values outside (this is the passage by value). And in the reference passage, it is possible to change the value within the function. To delve into the subject, I suggest starting around here (the question has examples in Java and C#, but serves to understand the general idea of the concept).
As for Python, there are those who argue that it has no passage by value or by reference, but a "third type" of passing parameters. I will not get into the merit of discussing the correct terminology (the documentation calls "pass by assignment"), but you can read here and here (Regardless of terminology, these links are interesting to better understand how it works). Anyway, to delve into the details of the language, I suggest reading also the Data Model of the same.
That said, we already know the problem of your code, which is to assume that the external variable could be changed within the function, just passing it as parameter. There are other problems as well, which is - in my opinion - complicate the algorithm for no reason (maybe not even break in so many functions), besides depending on the type of variable (and not its value) to determine program actions.
To another answer already gave a well simplified version of your code, for you see how it did not need to have complicated so much. I just wanted to add some more details.
A message from your code says: Para sair digite "sair"
. But in the code you check if it was typed only "s". So it was already inconsistent, because if it is typed "exit", it will not leave the program. A another answer suggested using startswith
(before it is edited, has now been corrected), but this is not a good solution because the program will accept any text that starts with "s" (that is, if you type "sapo", "s abc 123" and anything else that starts with "s", it leaves the program), and it doesn’t seem to be quite what you want it to be.
Another option would be:
import random
import sys
segredo = random.randint(1,20)
print(segredo)
def get_palpite():
try:
print('Para sair, digite "sair"')
entrada = input("Digite um número entre 1 e 20 para jogar: ")
if entrada == 'sair':
print("Jogo fechado")
sys.exit() # sai do programa
# não foi digitado "sair", tenta converter para número
palpite = int(entrada)
if 1 <= palpite <= 20:
return palpite
else: print(f'Erro: o número deve estar entre 1 e 20 e você digitou {palpite}')
except ValueError:
print(f"Erro: '{entrada}' não é um número")
while True:
if get_palpite() == segredo:
print("Acertou!")
else:
print("Errou!")
In the case, if entrada == 'sair'
only exits the program if it is typed exactly "exit". If you want to accept also "EXIT", "Exit" and other lower case combinations, you can use:
if entrada.lower() == 'sair':
If you want to accept both "leave" and only "s", you can switch to:
if entrada in ('sair', 's'):
Or even (if you want to accept "S", "Exit", "EXIT", etc):
if entrada.lower() in ('sair', 's'):
I also checked the values of the guess before returning it (if it is not a number, or if it is but it is not between 1 and 20, I ask you to type again).
That’s what I wanted @Jeanextreme002 to have explained, but he wouldn’t listen.
– Augusto Vasques
@Augustovasques I understood where is the error of my answer, only I do not even know how to edit my answer because hkotsubo already answered in detail and as I said, I do not know much about this subject. I am in a dilemma between erasing or not my answer because it is not as if it were 100% wrong, and deleting the answer would erase the comments with their explanations with the subject of passing value and reference.
– JeanExtreme002
@Jeanextreme002 that explanation was an orientation for you to improve the answer, the other day I saw that you were upset by taking a few downvotes. But the comments were like a gift is your and you make the use you want, after I sent it I no longer control the fate .
– Augusto Vasques
Okay then, I’ll try to edit.
– JeanExtreme002