Miss annotation, but no NameError?

Hi, Posts

>>> a:1

This typo doesn’t raise an exception or warning.
I think this should raise NameError: name ‘a’ is not defined.

1 Like

Interesting …

a:1
a:2 = "Monty"
print(a)

Output:

Monty

… I had originally deleted this post, but now that some replies have become attached to it, I have undeleted it and attempted to restore the above code to its original form. So now, thanks (in advance :grinning_face_with_smiling_eyes:) for the replies, @asvetlov, @steven.daprano, and @storchaka.

This is the type hint definition. No-op in runtime, used by type checkers only.

The real case:

a: int | None
if condition:
    a = 1
else:
    a = None
1 Like

The Python interpreter doesn’t care about annotations. They are almost
like comments, except that they have to be legal Python syntax.

So the line:

Oh this is ridiculous. Discuss just ate three quarters of my post, just
deleted it. Does anyone know where and how to report bugs for this
software?

Second attempt to send this. Hopefully discuss won’t delete half my
message this time.

The Python interpreter doesn’t care about annotations. They are almost
like comments, except that they have to be legal Python syntax.

So the line:

doesn’t really have any meaning to the interpreter. All the interpreter
does is check that it is legal syntax, and then store the annotation in
a special global variable called __annotations__.

The next line:

stores the annotation, and then assigns “Monty” to the variable a.

Checking annotations is 100% the responsibility of external tools, like
the “mypy” type-checker, linters or other programs. So if you have mypy
installed, and you check the file with it, you will get a result like
this:

[steve ~]$ cat example.py 
print(a)
[steve ~]$ mypy example.py 
example.py:1: error: Invalid type: try using Literal[1] instead?
example.py:2: error: Name "a" already defined on line 1
example.py:2: error: Invalid type: try using Literal[2] instead?
Found 3 errors in 1 file (checked 1 source file)

But the Python interpreter doesn’t care about any of that. It just goes
ahead and runs the code.

http://mypy-lang.org/

2 Likes

Seems “they are almost like comments” for Discuss too. :wink:

1 Like

Perhaps you were replying to my post in its original form, just as I was deleting it, and the system couldn’t handle that event gracefully. In any case, the post has now been undeleted, so as to eliminate the possibility that its eventual permanent deletion would fragment this thread.

Happy Halloween! guys

Thank you very much. Now I understood what Python is doing.

>>> a:1
>>> a
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'a' is not defined
>>> __annotations__
{'a': 1}

Still, it’s a bit confusing for me (it looks like the “expression assignment” of maxima).
I must add mypy to my emacs.

In this case it does change the behavior? The variable by itself would raise an error, but with the annotation it does not. The bare variable would be interpreted as an expression and the variable would be evaluated (generating an error since the variable is unassigned). When the annotation is added that doesn’t happen?

1 Like
a:input("Base: ")
b:input("Exponent: ")
print(int(__annotations__['a']) ** int(__annotations__['b']))

Execution:

Base: 2
Exponent: 8
256

So, who needs to create actual variables, when we can use annotations instead? :grinning:

1 Like

Yes, it changes the behaviour. As I said earlier, the interpreter checks

the syntax, and stores the annotation in a special global variable

called __annotations__. But the name itself is not looked up, which is

why there is no NameError.

(I’m sorry that parts of my earlier post were deleted by Discourse.)

Annotations are intended as type hints, a type of declaration. So in the

same way you can declare a global before it exists:

global a  # Does not evaluate a

so a type hint a:hint does not evaluate a.

By the way, in the case that your type hint is inside a function header:

def func(argument:Type)->Type:

the annotation is recorded in func.__annotations__ rather than in a

global variable.

1 Like