Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't an annotated variable be global?

Running

def function():
    global global_values
    global_values: str = []

gives

SyntaxError: annotated name 'global_values' can't be global

Is there any reason for this?

like image 642
ThatXliner Avatar asked Sep 07 '25 13:09

ThatXliner


2 Answers

This has been explained in PEP-526:

It is illegal to attempt to annotate variables subject to global or nonlocal in the same function scope:

def f():
    global x: int  # SyntaxError

def g():
    x: int  # Also a SyntaxError
    global x

The reason is that global and nonlocal don't own variables; therefore, the type annotations belong in the scope owning the variable.

The solution is to annotate the variable outside the function (i.e., in the global namespace), and remove type annotations inside the function's scope.

like image 117
blhsing Avatar answered Sep 10 '25 01:09

blhsing


So, as is often the case with very old language features, this is confusing. global in python is a statement that declares a name to be matching a key in the globals() dictionary-like container. If the key is not already in the globals() dictionary-like container, it will be added. It will default to a value of None at that time. If a variable is assigned in the global scope (and defined at that time), then the variable's name is added to the globals() dictionary-like container and the value is set to the value for the key matching the name in the globals() dictionary-like container.

So, the global keyword is a statement that adds a name to that globals() dictionary-like container. Unfortunately, you cannot do assignments to the variable in the same line as using global to add that variable's name to globals() dictionary-like container.

Because of this sadness, adding a name to globals() dictionary-like container will IMPLICITLY make it an Optional type in Python's typing world.

I still think this is a bug mentally. It is not obvious. It is not clear. It is not really sensible. Yet, there it is.

The right thing to do would be to have the ability to immediately assign a value to a global at the same time it is made global and thus have a non-Optional global type, and also remove the non-obvious, confusing troublesome edge case this is. Typing is great and would be lovely to have more of it in Python. It helps scale, it helps remove logical errors and ambiguities that cause difficult bugs. It highlights when you have situations where you have not accounted for a variable possibly being a type wholly incompatible with the code written.

like image 44
uchuugaka Avatar answered Sep 10 '25 03:09

uchuugaka