Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python variable and function annotation raises AttributeError

Although variable current_timestamp (and thus also the function return value) and variable time are datetime.datetime class objects, the following code raises AttributeError: type object 'datetime.datetime' has no attribute 'datetime'

from datetime import datetime

def current_time() -> datetime.datetime:
   
    current_timestamp: datetime.datetime = datetime.now()
    return current_timestamp

time: datetime.datetime = current_time()
print(time)

Changing only the annotation for the function return value and the time variable solves the problem.

from datetime import datetime

def current_time() -> datetime:
   
    current_timestamp: datetime.datetime = datetime.now()
    return current_timestamp

time: datetime = current_time()
print(time)

Can anyone explain why the annotation datetime.datetime raises only an AttributeError for the function return value and the time variable, but not for the current_timestamp variable?

I am running Python 3.8.

like image 944
finel Avatar asked Apr 11 '21 18:04

finel


1 Answers

From PEP 526, where this syntax is defined

Annotating a local variable will cause the interpreter to treat it as a local, even if it was never assigned to. Annotations for local variables will not be evaluated:

def f():
    x: NonexistentName  # No error.

However, if it is at a module or class level, then the type will be evaluated:

x: NonexistentName  # Error!
class X:
    var: NonexistentName  # Error!

In addition, at the module or class level, if the item being annotated is a simple name, then it and the annotation will be stored in the __annotations__ attribute of that module or class (mangled if private) as an ordered mapping from names to evaluated annotations.

So the reason is that annotations are meant to be a general-purpose tool, leaving open the possibility of using them for things other than type signatures. At the module or class level, you can get access to this information at runtime using reflection techniques, so the value has to exist and will be evaluated. When applied to a local variable, however, no reflection is available on local variables so the annotation is only useful to third-party tools parsing the code, hence Python itself has no reason to evaluate it.

It's worth noting that mypy will fail on the second example, and if you want to use an actual type checker you will have to correct the annotation in every place.

like image 155
Silvio Mayolo Avatar answered Oct 16 '22 18:10

Silvio Mayolo