30

This is somewhat academic, but nevertheless.

Python syntax forbids starting a variable name with a number, but this can be sidestepped like so:

>>> globals()['1a'] = 1
>>> globals()['1a']
1

Likewise for locals().

Does that mean that Python actually allows it, and that it's just not very visible?

Edit:

My question is not whether it is allowed; I am aware that it is formally not allowed in Python. The question is why can I work around it by addressing globals() directly, and if that breaks certain rules or guidelines, or if it has a good reason/application to allow that.

Aryan Beezadhur
  • 2,647
  • 1
  • 12
  • 31
steffen
  • 7,380
  • 8
  • 40
  • 78
  • 2
    The parser disallows it, but you can do it by hijacking `globals()`. But you're not really intended to do that. – Kevin Jan 31 '17 at 16:22
  • 8
    You can't use it as a variable later... so it isn't really a variable, even though it is in the same namespace. – tdelaney Jan 31 '17 at 16:26
  • Your answer (duplicate): http://stackoverflow.com/questions/342152/why-cant-variable-names-start-with-numbers – MichaelMMeskhi Jan 31 '17 at 16:37
  • Possible duplicate of [Why can't variable names start with numbers?](http://stackoverflow.com/questions/342152/why-cant-variable-names-start-with-numbers) – MichaelMMeskhi Jan 31 '17 at 16:37
  • @MichaelMMeskhi, not a dup, IMO. OP actually asks if his hack is sane, not about parsing rules. – kay Jan 31 '17 at 16:43
  • @Kay Hmmm, you are right. I didn't get OP's initial intentions – MichaelMMeskhi Jan 31 '17 at 16:47
  • 1
    @steffan Modifying `locals` doesn't work [https://docs.python.org/3/library/functions.html#locals] so you can only do this trick in `globals` – DavidW Feb 03 '17 at 11:58
  • 1
    @DavidW I just tried it... it works in Python 3.6.0 and 2.7.13 – steffen Feb 03 '17 at 12:51
  • @steffen So it looks like you're right in this case... Generally though messing with locals is a disaster: e.g. `def f(): locals()['a'] = 1; print(a)` (raises an error) or even `def f(): a=0; locals()['a']=1; print(a)` (prints 0) – DavidW Feb 03 '17 at 13:11

2 Answers2

24

Python parser forbids naming variables that way, for the sake of parsing numbers and variables separately, as naming a variable 1e1 would create a chaos - is it the number 10.0 or the variable 1e1?

"Python, please output for me 1e1!" - "Why is it 10.0? I stored 100 over there!"

But the variables are actually stored in a way that allows binding a string that starts with a number to a value, because that feature is no harm in hashing maps of any kind, and so using this "trick" you can achieve your wanted numeral-prefixed-name variable without hurting the parser severability.

I would say that technically, naming variables in that manner is not a violation to python guidelines, but it is highly discouraged, and as a rule unnecessary. Using globals for injecting variables is known as a very bad practice and this case should not be an outstanding.


Of course, python could have used an encloser to numerals like strings, say *123*, but I believe the intent of inventing python was to make programming easier, not stretching the limits of variable naming space.


Practically speaking, if you must use number-headed names you better do it with your own dictionary, rather than globals:

>>> number_headed_vars = {'1a': 100}
>>> number_headed_vars['1a']
100

That way you can create your own variables system - and avoid abusing globals().

Uriel
  • 13,905
  • 4
  • 21
  • 43
  • I suspect this was not implemented more because it would cause ambiguity in the grammar of the old parser (<=3.8). I believe it *could* be implemented with the new PEG parser (>=3.9) but I doubt the core-devs would deem it a necessary addition and therefore would vote against any PEP proposing this. – Minion Jim Aug 01 '20 at 10:46
7

This is what you can and can't do with that 1a in globals. You can't really use it in a variable, unless you use all of it's definition in globals (I mean accessing that dictionary), which makes it very uncomfortable for usage (another reason for not doing that).

Basically, 1a is not a real variable as a1 , as shown in the following output:

>>> globals()['1a'] = 1
>>> globals()['1a']
1

>>> a = 1a
File "<stdin>", line 1
    a = 1a
         ^
SyntaxError: invalid syntax

>>> a = globals()['1a']
>>> a
1

>>> globals()['a1'] = 5
>>> a = a1
>>> a
5
Ofer Arial
  • 1,054
  • 8
  • 20
  • 3
    Hi, came back to this question because of upvotes wave, and seen the sentence `"1a is not a real variable."`. While this makes sense, it isn't true. The problem isn't that `1a` isn't a "real" variable. The reason you can't use it in your code is because the parser **can not tokenize `1a` as a variable** (if it could, it would have worked perfectly, since is it stored normally in the `globals`). The rest is all good. – Uriel Oct 29 '17 at 17:12