Complementing the response of Maniero...
Python has a memory temporary, to stack, which is used to execute your code. Whenever you call a function, the return will be automatically stored in the stack. The difference between storing the return in a variable or not is what will happen after that.
When you assign the return to a variable, the Python interpreter will execute another instruction that moves the value of the stack for another independent memory, referencing the variable to the address of this value in this memory. Unlike some other languages, the variable/value ratio is not one for one. The interpreter will generate a table associating several variables to a given value (about this, you can search over [i]mutable data). On the internet you will usually see an association of this as variables being labels and not boxes that store a value.
Let’s see what the disassembler shows us the code below:
num = int(input("Digite um numero: "))
if num <= 10:
print("Ok, numero registrado")
Opcodes executed by the interpreter:
1 0 LOAD_NAME 0 (int)
2 LOAD_NAME 1 (input)
4 LOAD_CONST 0 ('Digite um numero: ')
6 CALL_FUNCTION 1
8 CALL_FUNCTION 1
10 STORE_NAME 2 (num)
3 12 LOAD_NAME 2 (num)
14 LOAD_CONST 1 (10)
16 COMPARE_OP 1 (<=)
18 POP_JUMP_IF_FALSE 28
4 20 LOAD_NAME 3 (print)
22 LOAD_CONST 2 ('Ok, numero registrado')
24 CALL_FUNCTION 1
26 POP_TOP
>> 28 LOAD_CONST 3 (None)
30 RETURN_VALUE
None
In sequence, it occurs:
- The object of name is loaded
int
, that will be a chargeable object;
- The object of name is loaded
input
, that will be a chargeable object;
- Loads the constant, storing it in the stack, of the kind string,
'Digite um numero: '
;
- The last function loaded is called,
input
, passing the top of stack as a parameter, storing the return at the top of the stack;
- The last function loaded is called,
int
, passing the top of stack as a parameter, storing the return at the top of the stack;
- Stores the value at the top of the stack in a location identified by
num
;
After that, basically the interpreter will access the value identified by num
, will load the necessary operators and execute the proper instructions. What we care about here are the instructions CALL_FUNCTION
and STORE_NAME
. We see the description of each according to the documentation:
STORE_NAME(namei)
Implements name = TOS
. namei
is the index of name in the attribute co_names
of the code Object. The Compiler tries to use STORE_FAST or STORE_GLOBAL if possible.
CALL_FUNCTION(argc)
Calls a callable Object with positional Arguments. argc
indicates the
number of positional Arguments. The top of the stack contains
positional Arguments, with the right-Most argument on top. Below the
Arguments is a callable Object to call. CALL_FUNCTION
Pops all
Arguments and the callable Object off the stack, calls the callable
Object with those Arguments, and pushes the Return value returned by
the callable Object.
Note: Read TOS
as top-of-stack (last value added to stack).
As commented, CALL_FUNCTION
removes from the top of stack the amount of values to be passed to the function that will be called and add the return back to the stack, while STORE_NAME
defines in the table an association between the name (variable) and the value at the top of the stack.
Due to this association with the variable and the value, in another memory, you will be able to access the value in the future through the variable. It will be persistent until the end of the execution of the variable’s scope. Different from when you do not assign the variable, because in this case the value is stored only in stack, being removed or ignored by the next statement to be executed.
You may not have noticed, but you implemented the two forms in your example. The return of int()
you assigned to the variable num
, but the return of input
you have not stored in a variable. So, go back to opcodes executed by the interpreter and see what happened:
1 0 LOAD_NAME 0 (int)
2 LOAD_NAME 1 (input)
4 LOAD_CONST 0 ('Digite um numero: ')
6 CALL_FUNCTION 1
8 CALL_FUNCTION 1
10 STORE_NAME 2 (num)
The first CALL_FUNCTION
will be responsible for calling the function input
, for she was the last to press stack. Note that no one is executed STORE_NAME
after the function call, since the return was not assigned to a variable. In fact, the return was stored at the top of the stack, as usual, but has already been removed by the next instruction, the CALL_FUNCTION
performing the function int
. That is, the return of input
is stored in the stack, used as a parameter per int
and gets lost.
The same happens when you do not assign the return to the variable num
:
if int(input("Digite um numero: ")) <= 10:
print("Ok, numero registrado")
Executing the following opcodes:
1 0 LOAD_NAME 0 (int)
2 LOAD_NAME 1 (input)
4 LOAD_CONST 0 ('Digite um numero: ')
6 CALL_FUNCTION 1
8 CALL_FUNCTION 1
10 LOAD_CONST 1 (10)
12 COMPARE_OP 1 (<=)
14 POP_JUMP_IF_FALSE 24
2 16 LOAD_NAME 2 (print)
18 LOAD_CONST 2 ('Ok, numero registrado')
20 CALL_FUNCTION 1
22 POP_TOP
>> 24 LOAD_CONST 3 (None)
26 RETURN_VALUE
None
Realize that instead of executing STORE_NAME
, the interpreter will now execute LOAD_CONST
, to put in the stack constant 10 and then run the comparison operator, COMPARE_OP
, which is a binary operator, thus requiring two operands which will be the two values at the top of the stack: constant 10 and the return of int
. After that, the return of int
will be lost.
To ask the user while he does not enter a valid value, I have already commented on this other answer:
Which comes down to:
while True:
try:
numero = int(input("Informe um número menor ou igual a 10: "))
if numero > 10:
raise ValueError("Número não pode ser maior que 10")
except ValueError as e:
print("Valor inválido:", e)
else:
break
print(numero)
See working on Repl.it
Note that in addition to checking whether the number read is less than 10, exceptions are also used, because the function int
throws an exception ValueError
if the input cannot be converted to an integer. A typical case is when the user enters with a letter instead of a number. Without capturing the exception, your program would end in this situation.
Without storing in the variable would then:
while True:
try:
if int(input("Informe um número menor ou igual a 10: ")) > 10:
raise ValueError("Número não pode ser maior que 10")
except ValueError as e:
print("Valor inválido:", e)
else:
break
print(r'Valor válido, mas não sei qual foi ¯\_(ツ)_/¯')
See working on Repl.it
Out of curiosity, this will be the opcode executed:
1 0 SETUP_LOOP 80 (to 82)
2 >> 2 SETUP_EXCEPT 28 (to 32)
3 4 LOAD_NAME 0 (int)
6 LOAD_NAME 1 (input)
8 LOAD_CONST 0 ('Informe um número menor ou igual a 10: ')
10 CALL_FUNCTION 1
12 CALL_FUNCTION 1
14 LOAD_CONST 1 (10)
16 COMPARE_OP 4 (>)
18 POP_JUMP_IF_FALSE 28
4 20 LOAD_NAME 2 (ValueError)
22 LOAD_CONST 2 ('Número não pode ser maior que 10')
24 CALL_FUNCTION 1
26 RAISE_VARARGS 1
>> 28 POP_BLOCK
30 JUMP_FORWARD 44 (to 76)
5 >> 32 DUP_TOP
34 LOAD_NAME 2 (ValueError)
36 COMPARE_OP 10 (exception match)
38 POP_JUMP_IF_FALSE 74
40 POP_TOP
42 STORE_NAME 3 (e)
44 POP_TOP
46 SETUP_FINALLY 16 (to 64)
6 48 LOAD_NAME 4 (print)
50 LOAD_CONST 3 ('Valor inválido:')
52 LOAD_NAME 3 (e)
54 CALL_FUNCTION 2
56 POP_TOP
58 POP_BLOCK
60 POP_EXCEPT
62 LOAD_CONST 4 (None)
>> 64 LOAD_CONST 4 (None)
66 STORE_NAME 3 (e)
68 DELETE_NAME 3 (e)
70 END_FINALLY
72 JUMP_ABSOLUTE 2
>> 74 END_FINALLY
8 >> 76 BREAK_LOOP
78 JUMP_ABSOLUTE 2
80 POP_BLOCK
10 >> 82 LOAD_NAME 4 (print)
84 LOAD_CONST 5 ('Valor válido, mas não sei qual foi ¯\_(ツ)_/¯')
86 CALL_FUNCTION 1
88 POP_TOP
90 LOAD_CONST 4 (None)
92 RETURN_VALUE
None
Practically duplicated of Accept only numerics in input
– Woss