Python 变量和函数注释引发 AttributeError

fin*_*nel 5 python python-3.x

尽管变量current_timestamp(因此也是函数返回值)和变量time是datetime.datetime类对象,但以下代码引发 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)
Run Code Online (Sandbox Code Playgroud)

仅更改函数返回值和time变量的注释即可解决问题。

from datetime import datetime

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

time: datetime = current_time()
print(time)
Run Code Online (Sandbox Code Playgroud)

谁能解释为什么注释datetime.datetime只为函数返回值和time变量引发 AttributeError而不是为current_timestamp变量引发?

我正在运行 Python 3.8。

Sil*_*olo 5

来自PEP 526,其中定义了此语法

注释局部变量将导致解释器将其视为局部变量,即使它从未被赋值。不会评估局部变量的注释:

def f():
    x: NonexistentName  # No error.
Run Code Online (Sandbox Code Playgroud)

但是,如果它是在模块或类级别,则类型将被评估:

x: NonexistentName  # Error!
class X:
    var: NonexistentName  # Error!
Run Code Online (Sandbox Code Playgroud)

此外,在模块或类级别,如果被注解的项目是一个简单的名称,那么它和注解将__annotations__作为从名称到评估注解的有序映射存储在该模块或类的属性中(如果私有则被破坏) .

所以原因是注解是一种通用工具,留下了将它们用于类型签名以外的东西的可能性。在模块或类级别,您可以使用反射技术在运行时访问此信息,因此该值必须存在并且将被评估。然而,当应用于局部变量时,局部变量没有反射可用,因此注释仅对解析代码的第三方工具有用,因此 Python 本身没有理由对其进行评估。

值得注意的是,这mypy将在第二个示例中失败,如果您想使用实际的类型检查器,则必须在每个地方更正注释。


小智 -1

答案仅在于您的实施。

当您从 datetime 导入 datetime 对象时,您期望函数从 datetime 模块返回 datetime 类型的对象。

datetime 模块下有许多类,其中之一就是 datetime。

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


time: datetime.datetime = current_time()
print(time)
Run Code Online (Sandbox Code Playgroud)

上面的实现显示了您是否想要像第一种情况中所述的那样具有函数注释。希望这有助于理解日期时间模块的正确导入。