Page 1 of 1
Private const() variables aren't defined
Posted: Wed Sep 11, 2019 4:51 pm
by cdwilson
Can someone help me understand why private const() variables aren't defined?
Code: Select all
>>> A = const(1)
>>> A
1
>>> _B = const(2)
>>> _B
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_B' isn't defined
Re: Private const() variables aren't defined
Posted: Thu Sep 12, 2019 6:42 am
by jimmo
This is because you're running this in the REPL.
There's a neat optimisation that MicroPython does to save memory based on hte convention that variables starting with _ are "private". So they will only apply to the scope of the current module being compiled.
Each statement executed on the REPL kind of like making a file containing that statement and compiling it.
But yeah, it works if you access it inside the same module. e.g. if you had foo.py:
Code: Select all
A = const(1)
_B = const(2)
print(A + _B)
that works just fine - the print will use _B correctly. If you run
Code: Select all
import foo
print(foo.A) # fine
print(foo._B) # doesn't exist
This feature is really useful for drivers where you might have a whole list of consts (e.g. I2C register addresses) but no point having them hang around as variables. It was implemented in
https://github.com/micropython/micropyt ... dc8edd5e0a likely based on Peter's suggestion in
viewtopic.php?f=3&t=1941
Re: Private const() variables aren't defined
Posted: Thu Sep 12, 2019 6:46 am
by kevinkk525
That is the theory.
But in practice this is not true.
I do very often use this in my code (although it is wrong):
Code: Select all
import foo
print(foo._private_variable)
And in the repl I can still use private variables, just not defined as const:
Code: Select all
>>> _B="hi"
>>> _B
'hi'
>>> _C=const(3)
>>> _C
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_C' isn't defined
Re: Private const() variables aren't defined
Posted: Thu Sep 12, 2019 7:45 am
by pythoncoder
It seems to work as I'd expect. Consider foo.py
Code: Select all
from micropython import const
_A = const(1)
_B = 2
C = 3
At the REPL
Code: Select all
>>> from foo import *
>>> dir()
['const', '__name__', 'C']
Names with underscores are not exported. This is standard Python. Now try:
Code: Select all
>>> import foo
>>> foo._A
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute '_A'
>>> foo._B
2
>>> foo.C
3
>>>
Python3 behaves similarly for _B and C (except that const is, of course, unsupported). The Python3 rule is that names beginning with an underscore are not imported when using
from foo import *. They are available in foo's namespace - but as you say it's poor form to access them.
Re: Private const() variables aren't defined
Posted: Thu Sep 12, 2019 8:00 am
by kevinkk525
Ah sorry, I understood that part wrong. Thanks Peter.
In that regard it does work as expected.
I guess the initial question has been answered by jimmo however it is strange to me because why can I declare _B with a string but not with const (in repl)? Shouldn't the same explanation apply to this too? If _B="hi" works then I would expect it to work with const too.
Code: Select all
>>> _B="hi"
>>> _B
'hi'
>>> _C=const(3)
>>> _C
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_C' isn't defined
Re: Private const() variables aren't defined
Posted: Thu Sep 12, 2019 8:43 am
by jimmo
kevinkk525 wrote: ↑Thu Sep 12, 2019 8:00 am
Shouldn't the same explanation apply to this too? If _B="hi" works then I would expect it to work with const too.
This optimisation exists purely to save memory - the const() variables starting with underscores don't even exist, their value just gets substituted at compile time.
But when you're not using const() (as in your _B="hi" example), the variable has to exist anyway, so maintaining cpython compatibility makes more sense. And as Peter showed, it does the right thing not showing up in dir().
Re: Private const() variables aren't defined
Posted: Thu Sep 12, 2019 9:01 am
by kevinkk525
I guess it makes sense although it is confusing in repl to have a different behaviour between const and strings.
Re: Private const() variables aren't defined
Posted: Thu Sep 12, 2019 9:59 pm
by cdwilson
Thanks for the explanations!
Each statement executed on the REPL kind of like making a file containing that statement and compiling it.
I didn't realize this was how the REPL worked. For anyone else coming across this later, this example makes it pretty clear:
Code: Select all
>>> _B = const(2)
>>> _B
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_B' isn't defined
>>> _B = const(2); _B
2
Re: Private const() variables aren't defined
Posted: Fri Sep 13, 2019 6:40 am
by pythoncoder
kevinkk525 wrote: ↑Thu Sep 12, 2019 9:01 am
I guess it makes sense although it is confusing in repl to have a different behaviour between const and strings.
The optimisation is important in device drivers where, for readability, you might want a lot of integer symbolic constants. This allows them to be used at zero cost (in RAM and in performance).